From d5c6bb9740a52d87b71d812e698d0e88abf10caa Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 13 Jun 2025 21:21:40 -0700 Subject: Add `/compress` command to force a compression of the context (#986) Related to https://b.corp.google.com/issues/423605555 - I figured this might be a simpler solution to start with, while still also being useful on its own even if we do implement that. --- .../cli/src/ui/hooks/slashCommandProcessor.test.ts | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'packages/cli/src/ui/hooks/slashCommandProcessor.test.ts') diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index c2873bd6..73669651 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -62,6 +62,7 @@ import { getMCPServerStatus, MCPDiscoveryState, getMCPDiscoveryState, + GeminiClient, } from '@gemini-cli/core'; import { useSessionStats } from '../contexts/SessionContext.js'; @@ -100,6 +101,8 @@ describe('useSlashCommandProcessor', () => { let mockOpenEditorDialog: ReturnType; let mockPerformMemoryRefresh: ReturnType; let mockSetQuittingMessages: ReturnType; + let mockTryCompressChat: ReturnType; + let mockGeminiClient: GeminiClient; let mockConfig: Config; let mockCorgiMode: ReturnType; const mockUseSessionStats = useSessionStats as Mock; @@ -115,8 +118,13 @@ describe('useSlashCommandProcessor', () => { mockOpenEditorDialog = vi.fn(); mockPerformMemoryRefresh = vi.fn().mockResolvedValue(undefined); mockSetQuittingMessages = vi.fn(); + mockTryCompressChat = vi.fn(); + mockGeminiClient = { + tryCompressChat: mockTryCompressChat, + } as unknown as GeminiClient; mockConfig = { getDebugMode: vi.fn(() => false), + getGeminiClient: () => mockGeminiClient, getSandbox: vi.fn(() => 'test-sandbox'), getModel: vi.fn(() => 'test-model'), getProjectRoot: vi.fn(() => '/test/dir'), @@ -944,4 +952,35 @@ Add any other context about the problem here. expect(commandResult).toBe(true); }); }); + + describe('/compress command', () => { + it('should call tryCompressChat(true)', async () => { + const { handleSlashCommand } = getProcessor(); + mockTryCompressChat.mockImplementationOnce(async (force?: boolean) => { + // TODO: Check that we have a pending compression item in the history. + expect(force).toBe(true); + return { + originalTokenCount: 100, + newTokenCount: 50, + }; + }); + + await act(async () => { + handleSlashCommand('/compress'); + }); + expect(mockGeminiClient.tryCompressChat).toHaveBeenCalledWith(true); + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.COMPRESSION, + compression: { + isPending: false, + originalTokenCount: 100, + newTokenCount: 50, + }, + }), + expect.any(Number), + ); + }); + }); }); -- cgit v1.2.3