From 6af7a5c58934c9a09774f0d38c3b87c2c877ecc5 Mon Sep 17 00:00:00 2001 From: Abhi <43648792+abhipatel12@users.noreply.github.com> Date: Mon, 16 Jun 2025 02:33:59 -0400 Subject: [PATCH] feat: clear should also clear chat history (#1008) --- .../ui/hooks/slashCommandProcessor.test.ts | 21 ++++++++++++++ .../cli/src/ui/hooks/slashCommandProcessor.ts | 7 +++-- packages/core/src/core/client.test.ts | 28 +++++++++++++++++++ packages/core/src/core/client.ts | 5 ++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index d9712d6e..68dc3ea9 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -340,6 +340,27 @@ describe('useSlashCommandProcessor', () => { expect(commandResult).toBe(true); }); + it('/clear should clear items, reset chat, and refresh static', async () => { + const mockResetChat = vi.fn(); + mockConfig = { + ...mockConfig, + getGeminiClient: () => ({ + resetChat: mockResetChat, + }), + } as unknown as Config; + + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = await handleSlashCommand('/clear'); + }); + + expect(mockClearItems).toHaveBeenCalled(); + expect(mockResetChat).toHaveBeenCalled(); + expect(mockRefreshStatic).toHaveBeenCalled(); + expect(commandResult).toBe(true); + }); + it('/editor should open editor dialog and return true', async () => { const { handleSlashCommand } = getProcessor(); let commandResult: SlashCommandActionReturn | boolean = false; diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts index 11e1247f..916af3e7 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts @@ -181,10 +181,11 @@ export const useSlashCommandProcessor = ( }, { name: 'clear', - description: 'clear the screen', - action: (_mainCommand, _subCommand, _args) => { - onDebugMessage('Clearing terminal.'); + description: 'clear the screen and conversation history', + action: async (_mainCommand, _subCommand, _args) => { + onDebugMessage('Clearing terminal and resetting chat.'); clearItems(); + await config?.getGeminiClient()?.resetChat(); console.clear(); refreshStatic(); }, diff --git a/packages/core/src/core/client.test.ts b/packages/core/src/core/client.test.ts index 032c9efc..675d1c26 100644 --- a/packages/core/src/core/client.test.ts +++ b/packages/core/src/core/client.test.ts @@ -331,6 +331,34 @@ describe('Gemini Client (client.ts)', () => { }); }); + describe('resetChat', () => { + it('should create a new chat session, clearing the old history', async () => { + // 1. Get the initial chat instance and add some history. + const initialChat = await client.getChat(); + const initialHistory = await client.getHistory(); + await client.addHistory({ + role: 'user', + parts: [{ text: 'some old message' }], + }); + const historyWithOldMessage = await client.getHistory(); + expect(historyWithOldMessage.length).toBeGreaterThan( + initialHistory.length, + ); + + // 2. Call resetChat. + await client.resetChat(); + + // 3. Get the new chat instance and its history. + const newChat = await client.getChat(); + const newHistory = await client.getHistory(); + + // 4. Assert that the chat instance is new and the history is reset. + expect(newChat).not.toBe(initialChat); + expect(newHistory.length).toBe(initialHistory.length); + expect(JSON.stringify(newHistory)).not.toContain('some old message'); + }); + }); + describe('sendMessageStream', () => { it('should return the turn instance after the stream is complete', async () => { // Arrange diff --git a/packages/core/src/core/client.ts b/packages/core/src/core/client.ts index 7cfb6b53..94c598bf 100644 --- a/packages/core/src/core/client.ts +++ b/packages/core/src/core/client.ts @@ -86,6 +86,11 @@ export class GeminiClient { chat.setHistory(history); } + async resetChat(): Promise { + this.chat = this.startChat(); + await this.chat; + } + private async getEnvironment(): Promise { const cwd = this.config.getWorkingDir(); const today = new Date().toLocaleDateString(undefined, {