mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-08-09 16:36:40 -07:00
Update filtering out thought parts from getHistoryTurns
This commit is contained in:
@@ -2282,6 +2282,62 @@ describe('GeminiChat', () => {
|
||||
text: 'actual conversational response',
|
||||
});
|
||||
});
|
||||
|
||||
it('should completely filter out thought parts from getHistoryTurns when context management is disabled but model is gemini-2/modern', () => {
|
||||
vi.mocked(mockConfig.isContextManagementEnabled).mockReturnValue(false);
|
||||
vi.mocked(mockConfig.getModel).mockReturnValue('gemini-2.5-pro');
|
||||
|
||||
chat.setHistory([
|
||||
{
|
||||
role: 'user',
|
||||
parts: [{ text: 'hello' }],
|
||||
},
|
||||
{
|
||||
role: 'model',
|
||||
parts: [
|
||||
{ text: 'internal monologue', thought: true } as unknown as Part,
|
||||
{ text: 'actual conversational response' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const turns = chat.getHistoryTurns(true);
|
||||
|
||||
expect(turns).toHaveLength(2);
|
||||
const modelTurn = turns[1];
|
||||
expect(modelTurn.content.parts).toHaveLength(1);
|
||||
expect(modelTurn.content.parts![0]).toEqual({
|
||||
text: 'actual conversational response',
|
||||
});
|
||||
});
|
||||
|
||||
it('should completely filter out thought parts from getHistoryTurns when model supports modern features', () => {
|
||||
vi.mocked(mockConfig.isContextManagementEnabled).mockReturnValue(false);
|
||||
vi.mocked(mockConfig.getModel).mockReturnValue('gemini-3.1-pro-preview');
|
||||
|
||||
chat.setHistory([
|
||||
{
|
||||
role: 'user',
|
||||
parts: [{ text: 'hello' }],
|
||||
},
|
||||
{
|
||||
role: 'model',
|
||||
parts: [
|
||||
{ text: 'internal monologue', thought: true } as unknown as Part,
|
||||
{ text: 'actual conversational response' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const turns = chat.getHistoryTurns(true);
|
||||
|
||||
expect(turns).toHaveLength(2);
|
||||
const modelTurn = turns[1];
|
||||
expect(modelTurn.content.parts).toHaveLength(1);
|
||||
expect(modelTurn.content.parts![0]).toEqual({
|
||||
text: 'actual conversational response',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ensureActiveLoopHasThoughtSignatures', () => {
|
||||
|
||||
@@ -30,7 +30,11 @@ import {
|
||||
getRetryErrorType,
|
||||
} from '../utils/retry.js';
|
||||
import type { ValidationRequiredError } from '../utils/googleQuotaErrors.js';
|
||||
import { resolveModel, supportsModernFeatures } from '../config/models.js';
|
||||
import {
|
||||
resolveModel,
|
||||
supportsModernFeatures,
|
||||
isGemini2Model,
|
||||
} from '../config/models.js';
|
||||
import { hasCycleInSchema } from '../tools/tools.js';
|
||||
import type { StructuredError } from './turn.js';
|
||||
import type { CompletedToolCall } from '../scheduler/types.js';
|
||||
@@ -766,9 +770,10 @@ export class GeminiChat {
|
||||
abortSignal,
|
||||
};
|
||||
|
||||
let contentsToUse: Content[] = supportsModernFeatures(modelToUse)
|
||||
? [...contentsForPreviewModel]
|
||||
: [...requestContents];
|
||||
let contentsToUse: Content[] =
|
||||
supportsModernFeatures(modelToUse) || isGemini2Model(modelToUse)
|
||||
? [...contentsForPreviewModel]
|
||||
: [...requestContents];
|
||||
|
||||
const hookSystem = this.context.config.getHookSystem();
|
||||
if (hookSystem) {
|
||||
@@ -810,9 +815,10 @@ export class GeminiChat {
|
||||
);
|
||||
lastModelToUse = modelToUse;
|
||||
// Re-evaluate contentsToUse based on the new model's feature support
|
||||
contentsToUse = supportsModernFeatures(modelToUse)
|
||||
? [...contentsForPreviewModel]
|
||||
: [...requestContents];
|
||||
contentsToUse =
|
||||
supportsModernFeatures(modelToUse) || isGemini2Model(modelToUse)
|
||||
? [...contentsForPreviewModel]
|
||||
: [...requestContents];
|
||||
}
|
||||
if (beforeModelResult.modifiedConfig) {
|
||||
Object.assign(config, beforeModelResult.modifiedConfig);
|
||||
@@ -956,9 +962,16 @@ export class GeminiChat {
|
||||
? extractCuratedHistory(this.agentHistory.get())
|
||||
: [...this.agentHistory.get()];
|
||||
|
||||
return this.context.config.isContextManagementEnabled()
|
||||
? scrubHistory(history)
|
||||
: history;
|
||||
if (this.context.config.isContextManagementEnabled()) {
|
||||
return scrubHistory(history);
|
||||
}
|
||||
|
||||
const model = this.context.config.getModel();
|
||||
if (isGemini2Model(model) || supportsModernFeatures(model)) {
|
||||
return stripThoughts(history);
|
||||
}
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1503,3 +1516,20 @@ export function coalesceConsecutiveRoles(
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function stripThoughts(history: HistoryTurn[]): HistoryTurn[] {
|
||||
return history.map((turn) => {
|
||||
if (!turn.content.parts) return turn;
|
||||
const hasThought = turn.content.parts.some((p) => p && p.thought);
|
||||
if (!hasThought) return turn;
|
||||
|
||||
const nonThoughtParts = turn.content.parts.filter((p) => p && !p.thought);
|
||||
return {
|
||||
id: turn.id,
|
||||
content: {
|
||||
...turn.content,
|
||||
parts: nonThoughtParts,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user