fix(cli): correct initial history length handling for chat commands (#15223)

This commit is contained in:
Sandy Tao
2025-12-17 14:04:02 -10:00
committed by GitHub
parent 5d13145995
commit 739c02bd6d
4 changed files with 16 additions and 20 deletions

View File

@@ -163,7 +163,6 @@ describe('chatCommand', () => {
mockGetHistory.mockReturnValue([
{ role: 'user', parts: [{ text: 'context for our chat' }] },
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
]);
result = await saveCommand?.action?.(mockContext, tag);
expect(result).toEqual({
@@ -208,9 +207,7 @@ describe('chatCommand', () => {
it('should save the conversation if overwrite is confirmed', async () => {
const history: Content[] = [
{ role: 'user', parts: [{ text: 'context for our chat' }] },
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
{ role: 'user', parts: [{ text: 'hello' }] },
{ role: 'model', parts: [{ text: 'Hi there!' }] },
];
mockGetHistory.mockReturnValue(history);
mockContext.overwriteConfirmed = true;
@@ -263,6 +260,7 @@ describe('chatCommand', () => {
it('should resume a conversation with matching authType', async () => {
const conversation: Content[] = [
{ role: 'user', parts: [{ text: 'system setup' }] },
{ role: 'user', parts: [{ text: 'hello gemini' }] },
{ role: 'model', parts: [{ text: 'hello world' }] },
];
@@ -285,6 +283,7 @@ describe('chatCommand', () => {
it('should block resuming a conversation with mismatched authType', async () => {
const conversation: Content[] = [
{ role: 'user', parts: [{ text: 'system setup' }] },
{ role: 'user', parts: [{ text: 'hello gemini' }] },
{ role: 'model', parts: [{ text: 'hello world' }] },
];
@@ -304,6 +303,7 @@ describe('chatCommand', () => {
it('should resume a legacy conversation without authType', async () => {
const conversation: Content[] = [
{ role: 'user', parts: [{ text: 'system setup' }] },
{ role: 'user', parts: [{ text: 'hello gemini' }] },
{ role: 'model', parts: [{ text: 'hello world' }] },
];
@@ -521,7 +521,6 @@ Hi there!`;
it('should inform if there is no conversation to share', async () => {
mockGetHistory.mockReturnValue([
{ role: 'user', parts: [{ text: 'context' }] },
{ role: 'model', parts: [{ text: 'context response' }] },
]);
const result = await shareCommand?.action?.(mockContext, 'my-chat.json');
expect(mockFs.writeFile).not.toHaveBeenCalled();

View File

@@ -17,6 +17,7 @@ import { CommandKind } from './types.js';
import {
decodeTagName,
type MessageActionReturn,
INITIAL_HISTORY_LENGTH,
} from '@google/gemini-cli-core';
import path from 'node:path';
import type {
@@ -131,7 +132,7 @@ const saveCommand: SlashCommand = {
}
const history = chat.getHistory();
if (history.length > 2) {
if (history.length > INITIAL_HISTORY_LENGTH) {
const authType = config?.getContentGeneratorConfig()?.authType;
await logger.saveCheckpoint({ history, authType }, tag);
return {
@@ -200,11 +201,8 @@ const resumeCommand: SlashCommand = {
};
const uiHistory: HistoryItemWithoutId[] = [];
let hasSystemPrompt = false;
let i = 0;
for (const item of conversation) {
i += 1;
for (const item of conversation.slice(INITIAL_HISTORY_LENGTH)) {
const text =
item.parts
?.filter((m) => !!m.text)
@@ -213,15 +211,11 @@ const resumeCommand: SlashCommand = {
if (!text) {
continue;
}
if (i === 1 && text.match(/context for our chat/)) {
hasSystemPrompt = true;
}
if (i > 2 || !hasSystemPrompt) {
uiHistory.push({
type: (item.role && rolemap[item.role]) || MessageType.GEMINI,
text,
} as HistoryItemWithoutId);
}
uiHistory.push({
type: (item.role && rolemap[item.role]) || MessageType.GEMINI,
text,
} as HistoryItemWithoutId);
}
return {
type: 'load_history',
@@ -343,10 +337,10 @@ const shareCommand: SlashCommand = {
const history = chat.getHistory();
// An empty conversation has two hidden messages that setup the context for
// An empty conversation has a hidden message that sets up the context for
// the chat. Thus, to check whether a conversation has been started, we
// can't check for length 0.
if (history.length <= 2) {
if (history.length <= INITIAL_HISTORY_LENGTH) {
return {
type: 'message',
messageType: 'info',

View File

@@ -73,6 +73,7 @@ export * from './utils/generateContentResponseUtilities.js';
export * from './utils/filesearch/fileSearch.js';
export * from './utils/errorParsing.js';
export * from './utils/workspaceContext.js';
export * from './utils/environmentContext.js';
export * from './utils/ignorePatterns.js';
export * from './utils/partUtils.js';
export * from './utils/promptIdContext.js';

View File

@@ -8,6 +8,8 @@ import type { Part, Content } from '@google/genai';
import type { Config } from '../config/config.js';
import { getFolderStructure } from './getFolderStructure.js';
export const INITIAL_HISTORY_LENGTH = 1;
/**
* Generates a string describing the current workspace directories and their structures.
* @param {Config} config - The runtime configuration and services.