Skip to content

Commit 9ddde0f

Browse files
Lightning00BladeDevtools-frontend LUCI CQ
authored andcommitted
[Freestyler] Clear all history
Show a footer item to clear all currently saved history entries Bug: 351752761 Change-Id: Ibd4dd406bb9f80fef647c3e694f5bca54010234a Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5982990 Auto-Submit: Nikolay Vitkov <[email protected]> Reviewed-by: Alex Rudenko <[email protected]> Commit-Queue: Nikolay Vitkov <[email protected]>
1 parent 6ccc3fe commit 9ddde0f

File tree

2 files changed

+117
-24
lines changed

2 files changed

+117
-24
lines changed

front_end/panels/freestyler/FreestylerPanel.test.ts

Lines changed: 91 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async function drainMicroTasks() {
3333
}
3434

3535
describeWithEnvironment('FreestylerPanel', () => {
36-
let mockView: sinon.SinonStub;
36+
let mockView: sinon.SinonStub<[Freestyler.Props, unknown, HTMLElement]>;
3737
let panel: Freestyler.FreestylerPanel;
3838

3939
beforeEach(() => {
@@ -611,17 +611,17 @@ describeWithEnvironment('FreestylerPanel', () => {
611611
syncInfo: getTestSyncInfo(),
612612
});
613613
panel.handleAction('freestyler.elements-floating-button');
614-
(mockView.lastCall.args.at(0) as Freestyler.Props).onTextSubmit('test');
614+
mockView.lastCall.args[0].onTextSubmit('test');
615615
await drainMicroTasks();
616616

617-
assert.deepEqual(mockView.lastCall.args.at(0).messages, [
617+
assert.deepEqual(mockView.lastCall.args[0].messages, [
618618
{
619-
entity: 'user',
619+
entity: Freestyler.ChatMessageEntity.USER,
620620
text: 'test',
621621
},
622622
{
623623
answer: 'test',
624-
entity: 'model',
624+
entity: Freestyler.ChatMessageEntity.MODEL,
625625
rpcId: undefined,
626626
suggestions: undefined,
627627
steps: [],
@@ -631,7 +631,7 @@ describeWithEnvironment('FreestylerPanel', () => {
631631
const button = toolbar!.shadowRoot!.querySelector('devtools-button[aria-label=\'New chat\']');
632632
assert.instanceOf(button, HTMLElement);
633633
dispatchClickEvent(button);
634-
assert.deepEqual(mockView.lastCall.args.at(0).messages, []);
634+
assert.deepEqual(mockView.lastCall.args[0].messages, []);
635635
});
636636

637637
it('should switch agents and restore history', async () => {
@@ -641,34 +641,33 @@ describeWithEnvironment('FreestylerPanel', () => {
641641
syncInfo: getTestSyncInfo(),
642642
});
643643
panel.handleAction('freestyler.elements-floating-button');
644-
(mockView.lastCall.args.at(0) as Freestyler.Props).onTextSubmit('User question to Freestyler?');
644+
mockView.lastCall.args[0].onTextSubmit('User question to Freestyler?');
645645
await drainMicroTasks();
646-
647-
assert.deepEqual(mockView.lastCall.args.at(0).messages, [
646+
assert.deepEqual(mockView.lastCall.args[0].messages, [
648647
{
649-
entity: 'user',
648+
entity: Freestyler.ChatMessageEntity.USER,
650649
text: 'User question to Freestyler?',
651650
},
652651
{
653652
answer: 'test',
654-
entity: 'model',
653+
entity: Freestyler.ChatMessageEntity.MODEL,
655654
rpcId: undefined,
656655
suggestions: undefined,
657656
steps: [],
658657
},
659658
]);
660659

661660
panel.handleAction('drjones.network-floating-button');
662-
(mockView.lastCall.args.at(0) as Freestyler.Props).onTextSubmit('User question to DrJones?');
661+
mockView.lastCall.args[0].onTextSubmit('User question to DrJones?');
663662
await drainMicroTasks();
664-
assert.deepEqual(mockView.lastCall.args.at(0).messages, [
663+
assert.deepEqual(mockView.lastCall.args[0].messages, [
665664
{
666-
entity: 'user',
665+
entity: Freestyler.ChatMessageEntity.USER,
667666
text: 'User question to DrJones?',
668667
},
669668
{
670669
answer: 'test',
671-
entity: 'model',
670+
entity: Freestyler.ChatMessageEntity.MODEL,
672671
rpcId: undefined,
673672
suggestions: undefined,
674673
steps: [],
@@ -686,14 +685,14 @@ describeWithEnvironment('FreestylerPanel', () => {
686685
contextMenu.invokeHandler(freestylerEntry.id());
687686

688687
await drainMicroTasks();
689-
assert.deepEqual(mockView.lastCall.args.at(0).messages, [
688+
assert.deepEqual(mockView.lastCall.args[0].messages, [
690689
{
691-
entity: 'user',
690+
entity: Freestyler.ChatMessageEntity.USER,
692691
text: 'User question to Freestyler?',
693692
},
694693
{
695694
answer: 'test',
696-
entity: 'model',
695+
entity: Freestyler.ChatMessageEntity.MODEL,
697696
rpcId: undefined,
698697
suggestions: undefined,
699698
steps: [],
@@ -709,17 +708,17 @@ describeWithEnvironment('FreestylerPanel', () => {
709708
syncInfo: getTestSyncInfo(),
710709
});
711710
panel.handleAction('freestyler.elements-floating-button');
712-
(mockView.lastCall.args.at(0) as Freestyler.Props).onTextSubmit('test');
711+
mockView.lastCall.args[0].onTextSubmit('test');
713712
await drainMicroTasks();
714713

715-
assert.deepEqual(mockView.lastCall.args.at(0).messages, [
714+
assert.deepEqual(mockView.lastCall.args[0].messages, [
716715
{
717-
entity: 'user',
716+
entity: Freestyler.ChatMessageEntity.USER,
718717
text: 'test',
719718
},
720719
{
721720
answer: 'test',
722-
entity: 'model',
721+
entity: Freestyler.ChatMessageEntity.MODEL,
723722
rpcId: undefined,
724723
suggestions: undefined,
725724
steps: [],
@@ -729,7 +728,75 @@ describeWithEnvironment('FreestylerPanel', () => {
729728
const button = toolbar!.shadowRoot!.querySelector('devtools-button[aria-label=\'Clear chat\']');
730729
assert.instanceOf(button, HTMLElement);
731730
dispatchClickEvent(button);
732-
assert.deepEqual(mockView.lastCall.args.at(0).messages, []);
733-
assert.deepEqual(mockView.lastCall.args.at(0).agentType, undefined);
731+
assert.deepEqual(mockView.lastCall.args[0].messages, []);
732+
assert.deepEqual(mockView.lastCall.args[0].agentType, undefined);
733+
});
734+
735+
it('should have empty state after clear chat history', async () => {
736+
panel = new Freestyler.FreestylerPanel(mockView, {
737+
aidaClient: getTestAidaClient(),
738+
aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,
739+
syncInfo: getTestSyncInfo(),
740+
});
741+
panel.handleAction('freestyler.elements-floating-button');
742+
mockView.lastCall.args[0].onTextSubmit('User question to Freestyler?');
743+
await drainMicroTasks();
744+
assert.deepEqual(mockView.lastCall.args[0].messages, [
745+
{
746+
entity: Freestyler.ChatMessageEntity.USER,
747+
text: 'User question to Freestyler?',
748+
},
749+
{
750+
answer: 'test',
751+
entity: Freestyler.ChatMessageEntity.MODEL,
752+
rpcId: undefined,
753+
suggestions: undefined,
754+
steps: [],
755+
},
756+
]);
757+
758+
panel.handleAction('drjones.network-floating-button');
759+
mockView.lastCall.args[0].onTextSubmit('User question to DrJones?');
760+
await drainMicroTasks();
761+
assert.deepEqual(mockView.lastCall.args[0].messages, [
762+
{
763+
entity: Freestyler.ChatMessageEntity.USER,
764+
text: 'User question to DrJones?',
765+
},
766+
{
767+
answer: 'test',
768+
entity: Freestyler.ChatMessageEntity.MODEL,
769+
rpcId: undefined,
770+
suggestions: undefined,
771+
steps: [],
772+
},
773+
]);
774+
775+
let toolbar = panel.contentElement.querySelector('.freestyler-left-toolbar');
776+
let button = toolbar!.shadowRoot!.querySelector('devtools-button[aria-label=\'History\']');
777+
assert.instanceOf(button, HTMLElement);
778+
let contextMenu = getMenu(() => {
779+
dispatchClickEvent(button!);
780+
});
781+
const clearAll = findMenuItemWithLabel(contextMenu.footerSection(), 'Clear chat history')!;
782+
assert.isDefined(clearAll);
783+
contextMenu.invokeHandler(clearAll.id());
784+
await drainMicroTasks();
785+
assert.deepEqual(mockView.lastCall.args[0].messages, []);
786+
assert.deepEqual(mockView.lastCall.args[0].agentType, undefined);
787+
788+
await drainMicroTasks();
789+
contextMenu.discard();
790+
await drainMicroTasks();
791+
792+
toolbar = panel.contentElement.querySelector('.freestyler-left-toolbar');
793+
button = toolbar!.shadowRoot!.querySelector('devtools-button[aria-label=\'History\']');
794+
assert.instanceOf(button, HTMLElement);
795+
contextMenu = getMenu(() => {
796+
dispatchClickEvent(button);
797+
});
798+
799+
// We don't show the context menu if there are not entries
800+
assert.isUndefined(contextMenu);
734801
});
735802
});

front_end/panels/freestyler/FreestylerPanel.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ const UIStrings = {
7272
*@description AI assistance UI text clearing the current chat session.
7373
*/
7474
clearChat: 'Clear chat',
75+
/**
76+
*@description AI assistance UI text that deletes all history entries.
77+
*/
78+
clearChatHistory: 'Clear chat history',
7579
};
7680

7781
/*
@@ -533,6 +537,10 @@ export class FreestylerPanel extends UI.Panel.Panel {
533537
}
534538

535539
#onHistoryClicked(event: Event): void {
540+
if ([...this.#agents].every(agent => agent.isEmpty)) {
541+
return;
542+
}
543+
536544
const contextMenu = new UI.ContextMenu.ContextMenu(event);
537545

538546
for (const agent of [...this.#agents].reverse()) {
@@ -552,9 +560,27 @@ export class FreestylerPanel extends UI.Panel.Panel {
552560
);
553561
}
554562

563+
contextMenu.footerSection().appendItem(
564+
i18nString(UIStrings.clearChatHistory),
565+
() => {
566+
this.#clearHistory();
567+
},
568+
);
569+
555570
void contextMenu.show();
556571
}
557572

573+
#clearHistory(): void {
574+
this.#agents = new Set();
575+
this.#freestylerAgent = this.#createFreestylerAgent();
576+
this.#drJonesFileAgent = this.#createDrJonesFileAgent();
577+
this.#drJonesNetworkAgent = this.#createDrJonesNetworkAgent();
578+
this.#drJonesPerformanceAgent = this.#createDrJonesPerformanceAgent();
579+
this.#viewProps.messages = [];
580+
this.#viewProps.agentType = undefined;
581+
this.doUpdate();
582+
}
583+
558584
#onDeleteClicked(): void {
559585
if (!this.#viewProps.agentType) {
560586
return;

0 commit comments

Comments
 (0)