code review followup for compress command (#1097)

Followup to https://github.com/google-gemini/gemini-cli/pull/986
This commit is contained in:
Jacob MacDonald 2025-06-17 08:44:54 -07:00 committed by GitHub
parent c3971754bf
commit e59c872b3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 39 additions and 18 deletions

View File

@ -23,7 +23,8 @@ export const CompressionMessage: React.FC<CompressionDisplayProps> = ({
}) => { }) => {
const text = compression.isPending const text = compression.isPending
? 'Compressing chat history' ? 'Compressing chat history'
: `Chat history compressed from ${compression.originalTokenCount} to ${compression.newTokenCount} tokens.`; : `Chat history compressed from ${compression.originalTokenCount ?? 'unknown'}` +
` to ${compression.newTokenCount ?? 'unknown'} tokens.`;
return ( return (
<Box flexDirection="row"> <Box flexDirection="row">

View File

@ -159,8 +159,8 @@ describe('useSlashCommandProcessor', () => {
process.env = { ...globalThis.process.env }; process.env = { ...globalThis.process.env };
}); });
const getProcessor = (showToolDescriptions: boolean = false) => { const getProcessorHook = (showToolDescriptions: boolean = false) =>
const { result } = renderHook(() => renderHook(() =>
useSlashCommandProcessor( useSlashCommandProcessor(
mockConfig, mockConfig,
[], [],
@ -178,8 +178,9 @@ describe('useSlashCommandProcessor', () => {
mockSetQuittingMessages, mockSetQuittingMessages,
), ),
); );
return result.current;
}; const getProcessor = (showToolDescriptions: boolean = false) =>
getProcessorHook(showToolDescriptions).result.current;
describe('/memory add', () => { describe('/memory add', () => {
it('should return tool scheduling info on valid input', async () => { it('should return tool scheduling info on valid input', async () => {
@ -1132,10 +1133,20 @@ Add any other context about the problem here.
describe('/compress command', () => { describe('/compress command', () => {
it('should call tryCompressChat(true)', async () => { it('should call tryCompressChat(true)', async () => {
const { handleSlashCommand } = getProcessor(); const hook = getProcessorHook();
mockTryCompressChat.mockImplementationOnce(async (force?: boolean) => { mockTryCompressChat.mockImplementationOnce(async (force?: boolean) => {
// TODO: Check that we have a pending compression item in the history.
expect(force).toBe(true); expect(force).toBe(true);
await act(async () => {
hook.rerender();
});
expect(hook.result.current.pendingHistoryItems).toContainEqual({
type: MessageType.COMPRESSION,
compression: {
isPending: true,
originalTokenCount: null,
newTokenCount: null,
},
});
return { return {
originalTokenCount: 100, originalTokenCount: 100,
newTokenCount: 50, newTokenCount: 50,
@ -1143,8 +1154,12 @@ Add any other context about the problem here.
}); });
await act(async () => { await act(async () => {
handleSlashCommand('/compress'); hook.result.current.handleSlashCommand('/compress');
}); });
await act(async () => {
hook.rerender();
});
expect(hook.result.current.pendingHistoryItems).toEqual([]);
expect(mockGeminiClient.tryCompressChat).toHaveBeenCalledWith(true); expect(mockGeminiClient.tryCompressChat).toHaveBeenCalledWith(true);
expect(mockAddItem).toHaveBeenNthCalledWith( expect(mockAddItem).toHaveBeenNthCalledWith(
2, 2,

View File

@ -760,6 +760,8 @@ Add any other context about the problem here.
type: MessageType.COMPRESSION, type: MessageType.COMPRESSION,
compression: { compression: {
isPending: true, isPending: true,
originalTokenCount: null,
newTokenCount: null,
}, },
}); });
try { try {

View File

@ -379,7 +379,8 @@ export const useGeminiStream = (
text: text:
`IMPORTANT: This conversation approached the input token limit for ${config.getModel()}. ` + `IMPORTANT: This conversation approached the input token limit for ${config.getModel()}. ` +
`A compressed context will be sent for future messages (compressed from: ` + `A compressed context will be sent for future messages (compressed from: ` +
`${eventValue.originalTokenCount} to ${eventValue.newTokenCount} tokens).`, `${eventValue?.originalTokenCount ?? 'unknown'} to ` +
`${eventValue?.newTokenCount ?? 'unknown'} tokens).`,
}, },
Date.now(), Date.now(),
), ),

View File

@ -55,8 +55,8 @@ export interface IndividualToolCallDisplay {
export interface CompressionProps { export interface CompressionProps {
isPending: boolean; isPending: boolean;
originalTokenCount?: number; originalTokenCount: number | null;
newTokenCount?: number; newTokenCount: number | null;
} }
export interface HistoryItemBase { export interface HistoryItemBase {

View File

@ -475,9 +475,11 @@ export class GeminiClient {
await cg.countTokens({ model: this.model, contents: newHistory }) await cg.countTokens({ model: this.model, contents: newHistory })
).totalTokens; ).totalTokens;
return { return originalTokenCount && newTokenCount
originalTokenCount, ? {
newTokenCount, originalTokenCount,
}; newTokenCount,
}
: null;
} }
} }

View File

@ -110,13 +110,13 @@ export type ServerGeminiErrorEvent = {
}; };
export interface ChatCompressionInfo { export interface ChatCompressionInfo {
originalTokenCount: number | undefined; originalTokenCount: number;
newTokenCount: number | undefined; newTokenCount: number;
} }
export type ServerGeminiChatCompressedEvent = { export type ServerGeminiChatCompressedEvent = {
type: GeminiEventType.ChatCompressed; type: GeminiEventType.ChatCompressed;
value: ChatCompressionInfo; value: ChatCompressionInfo | null;
}; };
export type ServerGeminiUsageMetadataEvent = { export type ServerGeminiUsageMetadataEvent = {