mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-06-26 19:27:36 -07:00
fix(cli): filter out tool response metadata from resumed session history
This commit is contained in:
@@ -1141,4 +1141,59 @@ describe('convertSessionToHistoryFormats', () => {
|
||||
throw new Error('Expected tool_group history item');
|
||||
}
|
||||
});
|
||||
|
||||
it('should NOT include tool response text messages in uiHistory', () => {
|
||||
const messages: MessageRecord[] = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'user',
|
||||
timestamp: new Date().toISOString(),
|
||||
content: [{ text: 'Hello' }],
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'gemini',
|
||||
timestamp: new Date().toISOString(),
|
||||
content: [{ text: 'Thinking...' }],
|
||||
toolCalls: [
|
||||
{
|
||||
id: 'call_1',
|
||||
name: 'read_file',
|
||||
args: { path: 'test.ts' },
|
||||
status: CoreToolCallStatus.Success,
|
||||
timestamp: new Date().toISOString(),
|
||||
result: [{ text: 'file content' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'user',
|
||||
timestamp: new Date().toISOString(),
|
||||
content: [
|
||||
{
|
||||
functionResponse: {
|
||||
name: 'read_file',
|
||||
response: { content: 'file content' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const { uiHistory } = convertSessionToHistoryFormats(messages);
|
||||
|
||||
const userMessages = uiHistory.filter((item) => item.type === 'user');
|
||||
expect(userMessages).toHaveLength(1);
|
||||
expect(userMessages[0].text).toBe('Hello');
|
||||
|
||||
const toolGroups = uiHistory.filter((item) => item.type === 'tool_group');
|
||||
expect(toolGroups).toHaveLength(1);
|
||||
|
||||
// Verify no message contains the "[Function Response" string which comes from verbose partToString
|
||||
const allText = uiHistory
|
||||
.map((item) => ('text' in item ? item.text : ''))
|
||||
.join(' ');
|
||||
expect(allText).not.toContain('[Function Response');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
import {
|
||||
checkExhaustive,
|
||||
partListUnionToString,
|
||||
SESSION_FILE_PREFIX,
|
||||
CoreToolCallStatus,
|
||||
type Storage,
|
||||
type ConversationRecord,
|
||||
type MessageRecord,
|
||||
loadConversationRecord,
|
||||
partToString,
|
||||
} from '@google/gemini-cli-core';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
@@ -171,7 +171,7 @@ export const extractFirstUserMessage = (messages: MessageRecord[]): string => {
|
||||
const userMessage = messages
|
||||
// First try filtering out slash commands.
|
||||
.filter((msg) => {
|
||||
const content = partListUnionToString(msg.content);
|
||||
const content = partToString(msg.content);
|
||||
return (
|
||||
!content.startsWith('/') &&
|
||||
!content.startsWith('?') &&
|
||||
@@ -186,9 +186,9 @@ export const extractFirstUserMessage = (messages: MessageRecord[]): string => {
|
||||
// Fallback to first user message even if it's a slash command
|
||||
const firstMsg = messages.find((msg) => msg.type === 'user');
|
||||
if (!firstMsg) return 'Empty conversation';
|
||||
content = cleanMessage(partListUnionToString(firstMsg.content));
|
||||
content = cleanMessage(partToString(firstMsg.content));
|
||||
} else {
|
||||
content = cleanMessage(partListUnionToString(userMessage.content));
|
||||
content = cleanMessage(partToString(userMessage.content));
|
||||
}
|
||||
|
||||
return content;
|
||||
@@ -312,14 +312,14 @@ export const getAllSessionFiles = async (
|
||||
|
||||
if (options.includeFullContent) {
|
||||
fullContent = content.messages
|
||||
.map((msg) => partListUnionToString(msg.content))
|
||||
.map((msg) => partToString(msg.content))
|
||||
.join(' ');
|
||||
messages = content.messages.map((msg) => ({
|
||||
role:
|
||||
msg.type === 'user'
|
||||
? ('user' as const)
|
||||
: ('assistant' as const),
|
||||
content: partListUnionToString(msg.content),
|
||||
content: partToString(msg.content),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -601,9 +601,9 @@ export function convertSessionToHistoryFormats(
|
||||
|
||||
// Add the message only if it has content
|
||||
const displayContentString = msg.displayContent
|
||||
? partListUnionToString(msg.displayContent)
|
||||
? partToString(msg.displayContent)
|
||||
: undefined;
|
||||
const contentString = partListUnionToString(msg.content);
|
||||
const contentString = partToString(msg.content);
|
||||
const uiText = displayContentString || contentString;
|
||||
|
||||
if (uiText.trim()) {
|
||||
|
||||
Reference in New Issue
Block a user