chrome-devtools-frontend 1.0.1611390 → 1.0.1613465
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/flowsheet.svg +1 -0
- package/front_end/core/common/Color.ts +3 -2
- package/front_end/core/host/AidaClientTypes.ts +5 -0
- package/front_end/core/host/AidaGcaTranslation.ts +1 -0
- package/front_end/core/platform/StringUtilities.ts +5 -0
- package/front_end/core/sdk/NetworkManager.ts +7 -0
- package/front_end/core/sdk/ResourceTreeModel.ts +2 -1
- package/front_end/core/sdk/Target.ts +1 -3
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/SupportedCSSProperties.js +4 -0
- package/front_end/generated/protocol.ts +12 -10
- package/front_end/models/greendev/Prototypes.ts +7 -4
- package/front_end/models/har/HARFormat.ts +30 -0
- package/front_end/models/har/Importer.ts +12 -1
- package/front_end/models/har/Log.ts +28 -0
- package/front_end/models/web_mcp/WebMCPModel.ts +73 -18
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +64 -25
- package/front_end/panels/ai_assistance/PatchWidget.ts +7 -23
- package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +3 -3
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +7 -0
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +21 -11
- package/front_end/panels/ai_assistance/components/ChatView.ts +4 -0
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +20 -10
- package/front_end/panels/ai_assistance/components/OptInChangeDialog.ts +179 -0
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +6 -2
- package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +1 -1
- package/front_end/panels/ai_assistance/components/optInChangeDialog.css +95 -0
- package/front_end/panels/ai_assistance/components/walkthroughView.css +19 -18
- package/front_end/panels/application/CookieItemsView.ts +3 -2
- package/front_end/panels/application/WebMCPView.ts +97 -6
- package/front_end/panels/application/webMCPView.css +7 -1
- package/front_end/panels/changes/ChangesView.ts +0 -12
- package/front_end/panels/common/common.ts +0 -1
- package/front_end/panels/console/ConsolePrompt.ts +2 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +2 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +3 -1
- package/front_end/panels/elements/elements-meta.ts +14 -0
- package/front_end/panels/network/NetworkLogView.ts +58 -28
- package/front_end/panels/recorder/RecorderController.ts +4 -4
- package/front_end/panels/settings/AISettingsTab.ts +39 -3
- package/front_end/panels/settings/SettingsScreen.ts +2 -2
- package/front_end/panels/sources/BreakpointEditDialog.ts +6 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +6 -0
- package/front_end/ui/legacy/SplitWidget.ts +9 -6
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +3 -3
- package/front_end/ui/legacy/components/source_frame/FontView.ts +101 -88
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +10 -0
- package/mcp/mcp.ts +1 -1
- package/package.json +1 -1
- package/front_end/panels/common/CopyChangesToPrompt.ts +0 -233
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
import {DisabledWidget} from './components/DisabledWidget.js';
|
|
45
45
|
import {ExploreWidget} from './components/ExploreWidget.js';
|
|
46
46
|
import {MarkdownRendererWithCodeBlock} from './components/MarkdownRendererWithCodeBlock.js';
|
|
47
|
+
import {OptInChangeDialog} from './components/OptInChangeDialog.js';
|
|
47
48
|
import {PerformanceAgentMarkdownRenderer} from './components/PerformanceAgentMarkdownRenderer.js';
|
|
48
49
|
import {StylingAgentMarkdownRenderer} from './components/StylingAgentMarkdownRenderer.js';
|
|
49
50
|
import {
|
|
@@ -252,6 +253,16 @@ const UIStringsNotTranslate = {
|
|
|
252
253
|
*/
|
|
253
254
|
inputDisclaimerForAccessibilityEnterpriseNoLogging:
|
|
254
255
|
'Chat messages and the selected Lighthouse report are sent to Google. The content you submit and that is generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
|
|
256
|
+
/**
|
|
257
|
+
* @description Disclaimer text right after the chat input when V2 is enabled.
|
|
258
|
+
*/
|
|
259
|
+
inputDisclaimerV2:
|
|
260
|
+
'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won’t always get it right.',
|
|
261
|
+
/**
|
|
262
|
+
* @description Disclaimer text right after the chat input when V2 is enabled and enterprise logging is off.
|
|
263
|
+
*/
|
|
264
|
+
inputDisclaimerEnterpriseNoLoggingV2:
|
|
265
|
+
'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google. The content submitted to and generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
|
|
255
266
|
} as const;
|
|
256
267
|
|
|
257
268
|
const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/AiAssistancePanel.ts', UIStrings);
|
|
@@ -306,9 +317,8 @@ async function getEmptyStateSuggestions(conversation?: AiAssistanceModel.AiConve
|
|
|
306
317
|
];
|
|
307
318
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
|
|
308
319
|
return [
|
|
309
|
-
{title: '
|
|
310
|
-
{title: '
|
|
311
|
-
{title: 'What does this Lighthouse report say about accessibility?', jslogContext: 'accessibility-default'},
|
|
320
|
+
{title: 'How can I fix accessibility issues on my page?', jslogContext: 'accessibility-default'},
|
|
321
|
+
{title: 'What accessibility issues exist on my page?', jslogContext: 'accessibility-default'},
|
|
312
322
|
];
|
|
313
323
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK:
|
|
314
324
|
|
|
@@ -780,11 +790,32 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
780
790
|
return await this.#conversationSummaryAgent.summarizeConversation(markdown);
|
|
781
791
|
},
|
|
782
792
|
onTextSubmit: async (
|
|
783
|
-
|
|
784
793
|
text: string, imageInput?: Host.AidaClient.Part,
|
|
785
794
|
multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
|
|
786
|
-
|
|
787
|
-
|
|
795
|
+
const submit = (): void => {
|
|
796
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceQuerySubmitted);
|
|
797
|
+
void this.#startConversation(text, imageInput, multimodalInputType);
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
const isAIV2Enabled = Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled;
|
|
801
|
+
const seenSetting =
|
|
802
|
+
Common.Settings.Settings.instance().moduleSetting('ai-assistance-v2-opt-in-change-dialog-seen');
|
|
803
|
+
if (isAIV2Enabled && !seenSetting.get()) {
|
|
804
|
+
OptInChangeDialog.show({
|
|
805
|
+
onGotIt: () => {
|
|
806
|
+
seenSetting.set(true);
|
|
807
|
+
submit();
|
|
808
|
+
},
|
|
809
|
+
onManageSettings: () => {
|
|
810
|
+
seenSetting.set(true);
|
|
811
|
+
this.#viewOutput.chatView?.setInputValue(text);
|
|
812
|
+
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
|
|
813
|
+
},
|
|
814
|
+
});
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
submit();
|
|
788
819
|
},
|
|
789
820
|
onInspectElementClick: this.#handleSelectElementClick.bind(this),
|
|
790
821
|
onFeedbackSubmit: this.#handleFeedbackSubmit.bind(this),
|
|
@@ -1397,46 +1428,54 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1397
1428
|
return i18nString(UIStrings.inputDisclaimerForEmptyState);
|
|
1398
1429
|
}
|
|
1399
1430
|
|
|
1400
|
-
const
|
|
1431
|
+
const loggingEnabled = Root.Runtime.hostConfig.aidaAvailability?.enterprisePolicyValue !==
|
|
1401
1432
|
Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING;
|
|
1433
|
+
|
|
1434
|
+
if (Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled) {
|
|
1435
|
+
if (loggingEnabled) {
|
|
1436
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerV2);
|
|
1437
|
+
}
|
|
1438
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerEnterpriseNoLoggingV2);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1402
1441
|
switch (this.#conversation.type) {
|
|
1403
1442
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING:
|
|
1404
|
-
if (
|
|
1405
|
-
return lockedString(UIStringsNotTranslate.
|
|
1443
|
+
if (loggingEnabled) {
|
|
1444
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForStyling);
|
|
1406
1445
|
}
|
|
1407
|
-
return lockedString(UIStringsNotTranslate.
|
|
1446
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForStylingEnterpriseNoLogging);
|
|
1408
1447
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.FILE:
|
|
1409
|
-
if (
|
|
1410
|
-
return lockedString(UIStringsNotTranslate.
|
|
1448
|
+
if (loggingEnabled) {
|
|
1449
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForFile);
|
|
1411
1450
|
}
|
|
1412
|
-
return lockedString(UIStringsNotTranslate.
|
|
1451
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForFileEnterpriseNoLogging);
|
|
1413
1452
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK:
|
|
1414
|
-
if (
|
|
1415
|
-
return lockedString(UIStringsNotTranslate.
|
|
1453
|
+
if (loggingEnabled) {
|
|
1454
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNetwork);
|
|
1416
1455
|
}
|
|
1417
|
-
return lockedString(UIStringsNotTranslate.
|
|
1456
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNetworkEnterpriseNoLogging);
|
|
1418
1457
|
|
|
1419
1458
|
// It is deliberate that both Performance agents use the same disclaimer
|
|
1420
1459
|
// text and this has been approved by Privacy.
|
|
1421
1460
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE:
|
|
1422
|
-
if (
|
|
1423
|
-
return lockedString(UIStringsNotTranslate.
|
|
1461
|
+
if (loggingEnabled) {
|
|
1462
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForPerformance);
|
|
1424
1463
|
}
|
|
1425
|
-
return lockedString(UIStringsNotTranslate.
|
|
1464
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForPerformanceEnterpriseNoLogging);
|
|
1426
1465
|
|
|
1427
1466
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
|
|
1428
|
-
if (
|
|
1429
|
-
return lockedString(UIStringsNotTranslate.
|
|
1467
|
+
if (loggingEnabled) {
|
|
1468
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForAccessibility);
|
|
1430
1469
|
}
|
|
1431
|
-
return lockedString(UIStringsNotTranslate.
|
|
1470
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForAccessibilityEnterpriseNoLogging);
|
|
1432
1471
|
|
|
1433
1472
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT:
|
|
1434
1473
|
|
|
1435
1474
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NONE:
|
|
1436
|
-
if (
|
|
1437
|
-
return lockedString(UIStringsNotTranslate.
|
|
1475
|
+
if (loggingEnabled) {
|
|
1476
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNoContext);
|
|
1438
1477
|
}
|
|
1439
|
-
return lockedString(UIStringsNotTranslate.
|
|
1478
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNoContextEnterpriseNoLogging);
|
|
1440
1479
|
}
|
|
1441
1480
|
}
|
|
1442
1481
|
|
|
@@ -13,7 +13,6 @@ import * as i18n from '../../core/i18n/i18n.js';
|
|
|
13
13
|
import * as Platform from '../../core/platform/platform.js';
|
|
14
14
|
import * as Root from '../../core/root/root.js';
|
|
15
15
|
import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
|
|
16
|
-
import * as GreenDev from '../../models/greendev/greendev.js';
|
|
17
16
|
import * as Persistence from '../../models/persistence/persistence.js';
|
|
18
17
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
19
18
|
import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
|
|
@@ -273,20 +272,6 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
273
272
|
nothing}`;
|
|
274
273
|
}
|
|
275
274
|
|
|
276
|
-
function renderCopyPrompt(changedCode?: string): LitTemplate {
|
|
277
|
-
if (!GreenDev.Prototypes.instance().isEnabled('copyToGemini') || !changedCode) {
|
|
278
|
-
return nothing;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// clang-format off
|
|
282
|
-
return html`<devtools-widget class="copy-to-prompt"
|
|
283
|
-
${widget(PanelCommon.CopyChangesToPrompt, {
|
|
284
|
-
workspaceDiff: input.workspaceDiff,
|
|
285
|
-
patchAgentCSSChange: changedCode,
|
|
286
|
-
})}></devtools-widget>`;
|
|
287
|
-
// clang-format on
|
|
288
|
-
}
|
|
289
|
-
|
|
290
275
|
function renderFooter(): LitTemplate {
|
|
291
276
|
if (input.savedToDisk) {
|
|
292
277
|
return nothing;
|
|
@@ -357,7 +342,6 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
357
342
|
</div>
|
|
358
343
|
` :
|
|
359
344
|
html`
|
|
360
|
-
${renderCopyPrompt(input.changeSummary)}
|
|
361
345
|
<devtools-button
|
|
362
346
|
@click=${input.onApplyToWorkspace}
|
|
363
347
|
.jslogContext=${'patch-widget.apply-to-workspace'}
|
|
@@ -435,7 +419,7 @@ export class PatchWidget extends UI.Widget.Widget {
|
|
|
435
419
|
#project?: Workspace.Workspace.Project;
|
|
436
420
|
#patchSources?: string;
|
|
437
421
|
#savedToDisk?: boolean;
|
|
438
|
-
#
|
|
422
|
+
#loggingEnabled: boolean; // Whether the enterprise setting is `ALLOW_WITHOUT_LOGGING` or not.
|
|
439
423
|
#patchSuggestionState = PatchSuggestionState.INITIAL;
|
|
440
424
|
#workspaceDiff = WorkspaceDiff.WorkspaceDiff.workspaceDiff();
|
|
441
425
|
#workspace = Workspace.Workspace.WorkspaceImpl.instance();
|
|
@@ -450,7 +434,7 @@ export class PatchWidget extends UI.Widget.Widget {
|
|
|
450
434
|
}) {
|
|
451
435
|
super(element);
|
|
452
436
|
this.#aidaClient = opts?.aidaClient ?? new Host.AidaClient.AidaClient();
|
|
453
|
-
this.#
|
|
437
|
+
this.#loggingEnabled = Root.Runtime.hostConfig.aidaAvailability?.enterprisePolicyValue !==
|
|
454
438
|
Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING;
|
|
455
439
|
this.#view = view;
|
|
456
440
|
|
|
@@ -514,9 +498,9 @@ export class PatchWidget extends UI.Widget.Widget {
|
|
|
514
498
|
projectPath,
|
|
515
499
|
projectType: this.#getSelectedProjectType(projectPath),
|
|
516
500
|
savedToDisk: this.#savedToDisk,
|
|
517
|
-
applyToWorkspaceTooltipText: this.#
|
|
518
|
-
lockedString(UIStringsNotTranslate.
|
|
519
|
-
lockedString(UIStringsNotTranslate.
|
|
501
|
+
applyToWorkspaceTooltipText: this.#loggingEnabled ?
|
|
502
|
+
lockedString(UIStringsNotTranslate.applyToWorkspaceTooltip) :
|
|
503
|
+
lockedString(UIStringsNotTranslate.applyToWorkspaceTooltipNoLogging),
|
|
520
504
|
onLearnMoreTooltipClick: this.#onLearnMoreTooltipClick.bind(this),
|
|
521
505
|
onApplyToWorkspace: this.#onApplyToWorkspace.bind(this),
|
|
522
506
|
onCancel: () => {
|
|
@@ -566,8 +550,8 @@ export class PatchWidget extends UI.Widget.Widget {
|
|
|
566
550
|
},
|
|
567
551
|
{
|
|
568
552
|
iconName: 'google',
|
|
569
|
-
content: this.#
|
|
570
|
-
|
|
553
|
+
content: this.#loggingEnabled ? lockedString(UIStringsNotTranslate.freDisclaimerTextPrivacy) :
|
|
554
|
+
lockedString(UIStringsNotTranslate.freDisclaimerTextPrivacyNoLogging),
|
|
571
555
|
},
|
|
572
556
|
{
|
|
573
557
|
iconName: 'warning',
|
|
@@ -233,14 +233,14 @@ export class SelectWorkspaceDialog extends UI.Widget.VBox {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
override performUpdate(): void {
|
|
236
|
-
const
|
|
236
|
+
const loggingEnabled = Root.Runtime.hostConfig.aidaAvailability?.enterprisePolicyValue !==
|
|
237
237
|
Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING;
|
|
238
238
|
|
|
239
239
|
const viewInput = {
|
|
240
240
|
folders: this.#folders,
|
|
241
241
|
selectedIndex: this.#selectedIndex,
|
|
242
|
-
selectProjectRootText:
|
|
243
|
-
|
|
242
|
+
selectProjectRootText: loggingEnabled ? lockedString(UIStringsNotTranslate.selectProjectRoot) :
|
|
243
|
+
lockedString(UIStringsNotTranslate.selectProjectRootNoLogging),
|
|
244
244
|
showAutomaticWorkspaceNudge: this.#automaticFileSystemManager.automaticFileSystem === null &&
|
|
245
245
|
this.#automaticFileSystemManager.availability === 'available',
|
|
246
246
|
onProjectSelected: (index: number) => {
|
|
@@ -161,6 +161,13 @@ Common.Settings.registerSettingExtension({
|
|
|
161
161
|
},
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
Common.Settings.registerSettingExtension({
|
|
165
|
+
category: Common.Settings.SettingCategory.AI,
|
|
166
|
+
settingName: 'ai-assistance-v2-opt-in-change-dialog-seen',
|
|
167
|
+
settingType: Common.Settings.SettingType.BOOLEAN,
|
|
168
|
+
defaultValue: false,
|
|
169
|
+
});
|
|
170
|
+
|
|
164
171
|
UI.ActionRegistration.registerActionExtension({
|
|
165
172
|
actionId: 'freestyler.main-menu',
|
|
166
173
|
contextTypes(): [] {
|
|
@@ -11,6 +11,7 @@ export * from './SelectWorkspaceDialog.js';
|
|
|
11
11
|
export * as ChatMessage from './components/ChatMessage.js';
|
|
12
12
|
export * as ExploreWidget from './components/ExploreWidget.js';
|
|
13
13
|
export * as ExportForAgentsDialog from './components/ExportForAgentsDialog.js';
|
|
14
|
+
export * as OptInChangeDialog from './components/OptInChangeDialog.js';
|
|
14
15
|
export * as PatchWidget from './PatchWidget.js';
|
|
15
16
|
export * as DisabledWidget from './components/DisabledWidget.js';
|
|
16
17
|
export * as WalkthroughView from './components/WalkthroughView.js';
|
|
@@ -157,9 +157,13 @@ const UIStringsNotTranslate = {
|
|
|
157
157
|
*/
|
|
158
158
|
completed: 'Completed',
|
|
159
159
|
/**
|
|
160
|
-
* @description Aria label for the
|
|
160
|
+
* @description Aria label for the spinner to be read by screen reader when a step is in progress.
|
|
161
161
|
*/
|
|
162
|
-
|
|
162
|
+
inProgress: 'In progress',
|
|
163
|
+
/**
|
|
164
|
+
* @description Aria label for the aborted icon to be read by screen reader
|
|
165
|
+
*/
|
|
166
|
+
aborted: 'Aborted',
|
|
163
167
|
/**
|
|
164
168
|
* @description Alt text for the image input (displayed in the chat messages) that has been sent to the model.
|
|
165
169
|
*/
|
|
@@ -208,6 +212,10 @@ const UIStringsNotTranslate = {
|
|
|
208
212
|
* @description Accessilility label for the button that shows the walkthrough when there are no widgets in the walkthrough.
|
|
209
213
|
*/
|
|
210
214
|
showThinking: 'Show thinking',
|
|
215
|
+
/**
|
|
216
|
+
* @description Accessilility label for the button that hides the walkthrough when there are no widgets in the walkthrough.
|
|
217
|
+
*/
|
|
218
|
+
hideThinking: 'Hide thinking',
|
|
211
219
|
} as const;
|
|
212
220
|
|
|
213
221
|
export interface Step {
|
|
@@ -467,7 +475,7 @@ function renderTitle(step: Step): Lit.LitTemplate {
|
|
|
467
475
|
html`<span class="paused">${lockedString(UIStringsNotTranslate.paused)}: </span>` :
|
|
468
476
|
Lit.nothing;
|
|
469
477
|
|
|
470
|
-
return html`<span class="title">${paused}${titleForStep(step)}</span>`;
|
|
478
|
+
return html`<span class="title" aria-label=${titleForStep(step)}>${paused}${titleForStep(step)}</span>`;
|
|
471
479
|
}
|
|
472
480
|
|
|
473
481
|
function renderStepCode(step: Step): Lit.LitTemplate {
|
|
@@ -577,10 +585,10 @@ function renderWalkthroughSidebarButton(
|
|
|
577
585
|
});
|
|
578
586
|
|
|
579
587
|
let accessibleLabel = title;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}
|
|
588
|
+
// If the agent is still thinking we want the accessibility label to include the current step title followed by Show/Hide thinking.
|
|
589
|
+
if (input.isLoading) {
|
|
590
|
+
const suffix = isExpanded ? UIStringsNotTranslate.hideThinking : UIStringsNotTranslate.showThinking;
|
|
591
|
+
accessibleLabel = `${titleForStep(lastStep)} ${i18n.i18n.lockedString(suffix)}`;
|
|
584
592
|
}
|
|
585
593
|
|
|
586
594
|
// clang-format off
|
|
@@ -683,7 +691,7 @@ function renderStepBadge({step, isLoading, isLast}: {
|
|
|
683
691
|
isLast: boolean,
|
|
684
692
|
}): Lit.LitTemplate {
|
|
685
693
|
if (isLoading && isLast && !step.requestApproval) {
|
|
686
|
-
return html`<devtools-spinner></devtools-spinner>`;
|
|
694
|
+
return html`<devtools-spinner aria-label=${lockedString(UIStringsNotTranslate.inProgress)}></devtools-spinner>`;
|
|
687
695
|
}
|
|
688
696
|
|
|
689
697
|
let iconName = 'checkmark';
|
|
@@ -691,10 +699,10 @@ function renderStepBadge({step, isLoading, isLast}: {
|
|
|
691
699
|
let role: 'button'|undefined = 'button';
|
|
692
700
|
if (isLast && step.requestApproval) {
|
|
693
701
|
role = undefined;
|
|
694
|
-
ariaLabel =
|
|
702
|
+
ariaLabel = lockedString(UIStringsNotTranslate.paused);
|
|
695
703
|
iconName = 'pause-circle';
|
|
696
704
|
} else if (step.canceled) {
|
|
697
|
-
ariaLabel = lockedString(UIStringsNotTranslate.
|
|
705
|
+
ariaLabel = lockedString(UIStringsNotTranslate.aborted);
|
|
698
706
|
iconName = 'cross';
|
|
699
707
|
}
|
|
700
708
|
|
|
@@ -938,6 +946,7 @@ function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTempla
|
|
|
938
946
|
const revealButton = html`
|
|
939
947
|
<devtools-button class="widget-reveal-button"
|
|
940
948
|
.variant=${Buttons.Button.Variant.TEXT}
|
|
949
|
+
.accessibleLabel=${lockedString(UIStringsNotTranslate.reveal)}
|
|
941
950
|
@click=${onReveal}
|
|
942
951
|
>
|
|
943
952
|
${response.customRevealTitle ?? lockedString(UIStringsNotTranslate.reveal)}
|
|
@@ -950,7 +959,7 @@ function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTempla
|
|
|
950
959
|
<div class=${classes}>
|
|
951
960
|
${response.title ? html`
|
|
952
961
|
<div class="widget-header">
|
|
953
|
-
<
|
|
962
|
+
<h3 class="widget-name">${response.title}</h3>
|
|
954
963
|
<div class="widget-reveal-container">
|
|
955
964
|
${revealButton}
|
|
956
965
|
</div>
|
|
@@ -1255,6 +1264,7 @@ function renderActions(input: ChatMessageViewInput, output: ViewOutput): Lit.Lit
|
|
|
1255
1264
|
.jslogContext=${'ai-export-for-agents'}
|
|
1256
1265
|
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
1257
1266
|
.iconName=${'copy'}
|
|
1267
|
+
aria-label=${lockedString(UIStringsNotTranslate.exportForAgents)}
|
|
1258
1268
|
@click=${input.onExportClick}
|
|
1259
1269
|
>${lockedString(UIStringsNotTranslate.exportForAgents)}</devtools-button>
|
|
1260
1270
|
${input.suggestions ? html`<div class="vertical-separator"></div>` : Lit.nothing}
|
|
@@ -282,6 +282,10 @@ export class ChatView extends HTMLElement {
|
|
|
282
282
|
textArea.focus();
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
setInputValue(text: string): void {
|
|
286
|
+
this.#output.input?.getWidget()?.setInputValue(text);
|
|
287
|
+
}
|
|
288
|
+
|
|
285
289
|
restoreScrollPosition(): void {
|
|
286
290
|
if (this.#scrollTop === undefined) {
|
|
287
291
|
return;
|
|
@@ -59,6 +59,8 @@ export const enum StateType {
|
|
|
59
59
|
CONVERSATION = 'conversation',
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
const DEFAULT_STATE_TYPE = StateType.PROMPT;
|
|
63
|
+
|
|
62
64
|
export interface State {
|
|
63
65
|
activeType: StateType;
|
|
64
66
|
promptText: string;
|
|
@@ -78,26 +80,25 @@ type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
|
|
|
78
80
|
export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
79
81
|
const isPrompt = input.state.activeType === StateType.PROMPT;
|
|
80
82
|
const buttonText = isPrompt ? i18nString(UIStrings.copyToClipboard) : i18nString(UIStrings.saveAsMarkdown);
|
|
81
|
-
const exportText = isPrompt
|
|
82
|
-
i18nString(UIStrings.generatingSummary) :
|
|
83
|
-
(isPrompt ? input.state.promptText : input.state.conversationText);
|
|
83
|
+
const exportText = isPrompt ? input.state.promptText : input.state.conversationText;
|
|
84
84
|
// clang-format off
|
|
85
85
|
|
|
86
86
|
render(html`
|
|
87
87
|
<style>${styles}</style>
|
|
88
88
|
<div class="export-for-agents-dialog">
|
|
89
89
|
<header>
|
|
90
|
-
<
|
|
90
|
+
<h1 id="export-for-agents-dialog-title" tabindex="-1">
|
|
91
91
|
${i18nString(UIStrings.exportForAgents)}
|
|
92
|
-
</
|
|
92
|
+
</h1>
|
|
93
93
|
</header>
|
|
94
|
-
<div class="state-selection">
|
|
94
|
+
<div class="state-selection" role="radiogroup" aria-labelledby="export-for-agents-dialog-title">
|
|
95
95
|
<label>
|
|
96
96
|
<input
|
|
97
97
|
type="radio"
|
|
98
98
|
value="prompt"
|
|
99
99
|
name="export-state"
|
|
100
100
|
.checked=${isPrompt}
|
|
101
|
+
aria-label=${i18nString(UIStrings.asPrompt)}
|
|
101
102
|
@change=${() => input.onStateChange(StateType.PROMPT)}
|
|
102
103
|
>
|
|
103
104
|
${i18nString(UIStrings.asPrompt)}
|
|
@@ -108,19 +109,20 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
|
108
109
|
value="conversation"
|
|
109
110
|
name="export-state"
|
|
110
111
|
.checked=${!isPrompt}
|
|
112
|
+
aria-label=${i18nString(UIStrings.asMarkdown)}
|
|
111
113
|
@change=${() => input.onStateChange(StateType.CONVERSATION)}
|
|
112
114
|
>
|
|
113
115
|
${i18nString(UIStrings.asMarkdown)}
|
|
114
116
|
</label>
|
|
115
117
|
</div>
|
|
116
118
|
<main>
|
|
117
|
-
${input.state.isPromptLoading ? html`
|
|
119
|
+
${isPrompt && input.state.isPromptLoading ? html`
|
|
118
120
|
<span class="prompt-loading">
|
|
119
121
|
<devtools-spinner></devtools-spinner>
|
|
120
122
|
${i18nString(UIStrings.generatingSummary)}
|
|
121
123
|
</span>
|
|
122
124
|
` : Lit.nothing}
|
|
123
|
-
<textarea readonly .value=${input.state.isPromptLoading ? '' : exportText}></textarea>
|
|
125
|
+
<textarea readonly .value=${isPrompt && input.state.isPromptLoading ? '' : exportText}></textarea>
|
|
124
126
|
</main>
|
|
125
127
|
<div class="disclaimer">${i18nString(UIStrings.disclaimer)}</div>
|
|
126
128
|
<footer>
|
|
@@ -130,6 +132,7 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
|
130
132
|
.jslogContext=${input.jslogContext}
|
|
131
133
|
.variant=${Buttons.Button.Variant.PRIMARY}
|
|
132
134
|
.disabled=${isPrompt && input.state.isPromptLoading}
|
|
135
|
+
.accessibleLabel=${buttonText}
|
|
133
136
|
>
|
|
134
137
|
${buttonText}
|
|
135
138
|
</devtools-button>
|
|
@@ -141,6 +144,7 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
|
141
144
|
};
|
|
142
145
|
|
|
143
146
|
export class ExportForAgentsDialog extends UI.Widget.VBox {
|
|
147
|
+
static #lastSelectedType: StateType = DEFAULT_STATE_TYPE;
|
|
144
148
|
readonly #view: View;
|
|
145
149
|
readonly #dialog: UI.Dialog.Dialog;
|
|
146
150
|
#state: State;
|
|
@@ -157,7 +161,7 @@ export class ExportForAgentsDialog extends UI.Widget.VBox {
|
|
|
157
161
|
super();
|
|
158
162
|
this.#dialog = options.dialog;
|
|
159
163
|
this.#state = {
|
|
160
|
-
activeType:
|
|
164
|
+
activeType: ExportForAgentsDialog.#lastSelectedType,
|
|
161
165
|
promptText: typeof options.promptText === 'string' ? options.promptText : '',
|
|
162
166
|
conversationText: options.markdownText,
|
|
163
167
|
isPromptLoading: typeof options.promptText !== 'string',
|
|
@@ -176,8 +180,13 @@ export class ExportForAgentsDialog extends UI.Widget.VBox {
|
|
|
176
180
|
this.requestUpdate();
|
|
177
181
|
}
|
|
178
182
|
|
|
183
|
+
static clearPersistedViewState(): void {
|
|
184
|
+
ExportForAgentsDialog.#lastSelectedType = DEFAULT_STATE_TYPE;
|
|
185
|
+
}
|
|
186
|
+
|
|
179
187
|
#onStateChange = (newState: StateType): void => {
|
|
180
188
|
this.#state.activeType = newState;
|
|
189
|
+
ExportForAgentsDialog.#lastSelectedType = newState;
|
|
181
190
|
this.requestUpdate();
|
|
182
191
|
};
|
|
183
192
|
|
|
@@ -191,9 +200,10 @@ export class ExportForAgentsDialog extends UI.Widget.VBox {
|
|
|
191
200
|
onButtonClick = (event: Event): void => {
|
|
192
201
|
event.preventDefault();
|
|
193
202
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.#state.promptText);
|
|
194
|
-
Snackbars.Snackbar.Snackbar.show({
|
|
203
|
+
const snackbar = Snackbars.Snackbar.Snackbar.show({
|
|
195
204
|
message: i18nString(UIStrings.copiedToClipboard),
|
|
196
205
|
});
|
|
206
|
+
snackbar.setAttribute('aria-label', i18nString(UIStrings.copiedToClipboard));
|
|
197
207
|
this.#dialog.hide();
|
|
198
208
|
};
|
|
199
209
|
break;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as i18n from '../../../core/i18n/i18n.js';
|
|
6
|
+
import * as Root from '../../../core/root/root.js';
|
|
7
|
+
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
8
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
|
9
|
+
import * as Lit from '../../../ui/lit/lit.js';
|
|
10
|
+
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
11
|
+
|
|
12
|
+
import styles from './optInChangeDialog.css.js';
|
|
13
|
+
|
|
14
|
+
const {html, render} = Lit;
|
|
15
|
+
|
|
16
|
+
const UIStrings = {
|
|
17
|
+
/**
|
|
18
|
+
* @description Title for the opt-in change dialog.
|
|
19
|
+
*/
|
|
20
|
+
title: 'AI assistance just got better',
|
|
21
|
+
/**
|
|
22
|
+
* @description First point in the opt-in change dialog, describing the new integration.
|
|
23
|
+
*/
|
|
24
|
+
integrationPoint:
|
|
25
|
+
'AI assistance is now integrated with Application and Lighthouse panels, and pulls context from data sources simultaneously',
|
|
26
|
+
/**
|
|
27
|
+
* @description Second point in the opt-in change dialog, describing the new widgets.
|
|
28
|
+
*/
|
|
29
|
+
widgetPoint: 'Use widgets to verify results or jump to source data for select debugging cases',
|
|
30
|
+
/**
|
|
31
|
+
* @description Third point in the opt-in change dialog (disclaimer) for regular users.
|
|
32
|
+
*/
|
|
33
|
+
privacyDisclaimer:
|
|
34
|
+
'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won’t always get it right.',
|
|
35
|
+
/**
|
|
36
|
+
* @description Third point in the opt-in change dialog (disclaimer) for enterprise users with logging disabled.
|
|
37
|
+
*/
|
|
38
|
+
privacyDisclaimerEnterpriseNoLogging:
|
|
39
|
+
'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google. The content submitted to and generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
|
|
40
|
+
/**
|
|
41
|
+
* @description Button text for managing settings.
|
|
42
|
+
*/
|
|
43
|
+
manageSettings: 'Manage in settings',
|
|
44
|
+
/**
|
|
45
|
+
* @description Button text for acknowledging the changes.
|
|
46
|
+
*/
|
|
47
|
+
gotIt: 'Got it',
|
|
48
|
+
} as const;
|
|
49
|
+
|
|
50
|
+
const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/components/OptInChangeDialog.ts', UIStrings);
|
|
51
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
52
|
+
|
|
53
|
+
interface ViewInput {
|
|
54
|
+
onGotIt: () => void;
|
|
55
|
+
onManageSettings: () => void;
|
|
56
|
+
loggingEnabled: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
|
|
60
|
+
|
|
61
|
+
export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
62
|
+
const disclaimer = input.loggingEnabled ? i18nString(UIStrings.privacyDisclaimer) :
|
|
63
|
+
i18nString(UIStrings.privacyDisclaimerEnterpriseNoLogging);
|
|
64
|
+
// clang-format off
|
|
65
|
+
render(html`
|
|
66
|
+
<style>${styles}</style>
|
|
67
|
+
<div class="opt-in-change-dialog" jslog=${VisualLogging.dialog('ai-v2-opt-in-change-dialog')}>
|
|
68
|
+
<header>
|
|
69
|
+
<div class="header-icon-container">
|
|
70
|
+
<devtools-icon name="smart-assistant" role="presentation"></devtools-icon>
|
|
71
|
+
</div>
|
|
72
|
+
<h1 tabindex="-1">
|
|
73
|
+
${i18nString(UIStrings.title)}
|
|
74
|
+
</h1>
|
|
75
|
+
</header>
|
|
76
|
+
<main>
|
|
77
|
+
<div class="item">
|
|
78
|
+
<devtools-icon name="lightbulb-spark" role="presentation"></devtools-icon>
|
|
79
|
+
<div class="text">${i18nString(UIStrings.integrationPoint)}</div>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="item">
|
|
82
|
+
<devtools-icon name="flowsheet" role="presentation"></devtools-icon>
|
|
83
|
+
<div class="text">${i18nString(UIStrings.widgetPoint)}</div>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="item">
|
|
86
|
+
<devtools-icon name="google" role="presentation"></devtools-icon>
|
|
87
|
+
<div class="text">${disclaimer}</div>
|
|
88
|
+
</div>
|
|
89
|
+
</main>
|
|
90
|
+
<footer>
|
|
91
|
+
<div class="right-buttons">
|
|
92
|
+
<devtools-button
|
|
93
|
+
@click=${input.onManageSettings}
|
|
94
|
+
.jslogContext=${'ai-assistance-v2-opt-in.manage-settings'}
|
|
95
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
96
|
+
.accessibleLabel=${i18nString(UIStrings.manageSettings)}
|
|
97
|
+
>
|
|
98
|
+
${i18nString(UIStrings.manageSettings)}
|
|
99
|
+
</devtools-button>
|
|
100
|
+
<devtools-button
|
|
101
|
+
@click=${input.onGotIt}
|
|
102
|
+
.jslogContext=${'ai-assistance-v2-opt-in.got-it'}
|
|
103
|
+
.variant=${Buttons.Button.Variant.PRIMARY}
|
|
104
|
+
.accessibleLabel=${i18nString(UIStrings.gotIt)}
|
|
105
|
+
>
|
|
106
|
+
${i18nString(UIStrings.gotIt)}
|
|
107
|
+
</devtools-button>
|
|
108
|
+
</div>
|
|
109
|
+
</footer>
|
|
110
|
+
</div>
|
|
111
|
+
`, target);
|
|
112
|
+
// clang-format on
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export class OptInChangeDialog extends UI.Widget.VBox {
|
|
116
|
+
readonly #view: View;
|
|
117
|
+
readonly #onGotIt: () => void;
|
|
118
|
+
readonly #onManageSettings: () => void;
|
|
119
|
+
|
|
120
|
+
constructor(
|
|
121
|
+
options: {
|
|
122
|
+
onGotIt: () => void,
|
|
123
|
+
onManageSettings: () => void,
|
|
124
|
+
},
|
|
125
|
+
view: View = DEFAULT_VIEW) {
|
|
126
|
+
super();
|
|
127
|
+
this.#onGotIt = options.onGotIt;
|
|
128
|
+
this.#onManageSettings = options.onManageSettings;
|
|
129
|
+
this.#view = view;
|
|
130
|
+
|
|
131
|
+
this.requestUpdate();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
override performUpdate(): void {
|
|
135
|
+
const loggingEnabled = Root.Runtime.hostConfig.aidaAvailability?.enterprisePolicyValue !==
|
|
136
|
+
Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING;
|
|
137
|
+
|
|
138
|
+
const viewInput = {
|
|
139
|
+
onGotIt: this.#onGotIt,
|
|
140
|
+
onManageSettings: this.#onManageSettings,
|
|
141
|
+
loggingEnabled,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
this.#view(viewInput, undefined, this.contentElement);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
focusTitle(): void {
|
|
148
|
+
this.contentElement.querySelector('h1')?.focus();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static show(options: {
|
|
152
|
+
onGotIt: () => void,
|
|
153
|
+
onManageSettings: () => void,
|
|
154
|
+
}): void {
|
|
155
|
+
const dialog = new UI.Dialog.Dialog();
|
|
156
|
+
dialog.setAriaLabel(i18nString(UIStrings.title));
|
|
157
|
+
dialog.setOutsideClickCallback(event => event.consume(true));
|
|
158
|
+
dialog.setCloseOnEscape(false);
|
|
159
|
+
dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);
|
|
160
|
+
dialog.setDimmed(true);
|
|
161
|
+
|
|
162
|
+
const optInChangeDialog = new OptInChangeDialog({
|
|
163
|
+
onGotIt: () => {
|
|
164
|
+
dialog.hide();
|
|
165
|
+
options.onGotIt();
|
|
166
|
+
},
|
|
167
|
+
onManageSettings: () => {
|
|
168
|
+
dialog.hide();
|
|
169
|
+
options.onManageSettings();
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
optInChangeDialog.show(dialog.contentElement);
|
|
173
|
+
|
|
174
|
+
void optInChangeDialog.updateComplete.then(() => {
|
|
175
|
+
dialog.show();
|
|
176
|
+
optInChangeDialog.focusTitle();
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|