diff --git a/packages/core/src/core/historyManager.ts b/packages/core/src/core/historyManager.ts index 0a22b47689..8ff57791d5 100644 --- a/packages/core/src/core/historyManager.ts +++ b/packages/core/src/core/historyManager.ts @@ -217,14 +217,6 @@ export class HistoryManager { this.elidedCallIds.add(callId); } - /** - * Clears elision markers. Usually called at the start of a new root-level turn. - */ - clearElisions(): void { - this.elidedCallIds.clear(); - this.elidedIndices.clear(); - } - /** * Records a distilled result for a tool call. */ @@ -246,6 +238,21 @@ export class HistoryManager { getHistoryForRequest(userContent: Content): Content[] { const projection = this.getProjection({ curated: true, addMetadata: true }); + // PROJECT CLARITY: Filter the userContent being sent to ensure elided parts (e.g. meta-tool responses) + // are not sent to the model even if they are part of the current turn. + const filteredParts = this.filterParts(userContent.parts || []); + + // If the turn is empty after filtering (or was empty to begin with, like a re-prompt), + // we just return the projection as-is. This avoids sending a vestigial empty turn. + if (filteredParts.length === 0) { + return projection; + } + + const filteredUserContent: Content = { + ...userContent, + parts: filteredParts, + }; + if ( projection.length > 0 && projection[projection.length - 1].role === 'user' @@ -254,12 +261,12 @@ export class HistoryManager { const lastTurn = projection[projection.length - 1]; const mergedTurn: Content = { ...lastTurn, - parts: [...(lastTurn.parts || []), ...(userContent.parts || [])], + parts: [...(lastTurn.parts || []), ...(filteredUserContent.parts || [])], }; return [...projection.slice(0, -1), mergedTurn]; } - return [...projection, userContent]; + return [...projection, filteredUserContent]; } /** @@ -355,7 +362,10 @@ export class HistoryManager { if (nextFilteredParts.length === 0) continue; modelOutput.push({ ...nextContent, parts: nextFilteredParts }); - if (isValid && !isValidContent({ ...nextContent, parts: nextFilteredParts })) { + if ( + isValid && + !isValidContent({ ...nextContent, parts: nextFilteredParts }) + ) { isValid = false; } } diff --git a/packages/core/src/tools/compress.ts b/packages/core/src/tools/compress.ts index 049babc49f..f7eb9dab18 100644 --- a/packages/core/src/tools/compress.ts +++ b/packages/core/src/tools/compress.ts @@ -19,7 +19,7 @@ import type { MessageBus } from '../confirmation-bus/message-bus.js'; import type { Config } from '../config/config.js'; import type { GeminiChat } from '../core/geminiChat.js'; import { CompressionStatus } from '../core/compression-status.js'; -import type { ShellExecutionConfig } from 'src/services/shellExecutionService.js'; +import type { ShellExecutionConfig } from '../services/shellExecutionService.js'; import { debugLogger } from '../utils/debugLogger.js'; class CompressInvocation extends BaseToolInvocation<