mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-22 02:54:31 -07:00
continuous session
This commit is contained in:
@@ -63,7 +63,7 @@ import {
|
||||
} from './types.js';
|
||||
import type { AnyDeclarativeTool, AnyToolInvocation } from '../tools/tools.js';
|
||||
import type { ToolCallRequestInfo } from '../scheduler/types.js';
|
||||
import { CompressionStatus } from '../core/turn.js';
|
||||
import { CompressionStatus } from '../core/compression-status.js';
|
||||
import { ChatCompressionService } from '../services/chatCompressionService.js';
|
||||
import type {
|
||||
ModelConfigKey,
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from '@google/genai';
|
||||
import { ToolRegistry } from '../tools/tool-registry.js';
|
||||
import { DiscoveredMCPTool } from '../tools/mcp-tool.js';
|
||||
import { CompressionStatus } from '../core/turn.js';
|
||||
import { CompressionStatus } from '../core/compression-status.js';
|
||||
import { type ToolCallRequestInfo } from '../scheduler/types.js';
|
||||
import { ChatCompressionService } from '../services/chatCompressionService.js';
|
||||
import { getDirectoryContextString } from '../utils/environmentContext.js';
|
||||
|
||||
@@ -33,6 +33,8 @@ import { WebFetchTool } from '../tools/web-fetch.js';
|
||||
import { MemoryTool, setGeminiMdFilename } from '../tools/memoryTool.js';
|
||||
import { WebSearchTool } from '../tools/web-search.js';
|
||||
import { AskUserTool } from '../tools/ask-user.js';
|
||||
import { CheckpointStateTool } from '../tools/checkpoint-state.js';
|
||||
import { CompressTool } from '../tools/compress.js';
|
||||
import { ExitPlanModeTool } from '../tools/exit-plan-mode.js';
|
||||
import { EnterPlanModeTool } from '../tools/enter-plan-mode.js';
|
||||
import { GeminiClient } from '../core/client.js';
|
||||
@@ -104,6 +106,8 @@ import {
|
||||
} from '../services/modelConfigService.js';
|
||||
import { DEFAULT_MODEL_CONFIGS } from './defaultModelConfigs.js';
|
||||
import { ContextManager } from '../services/contextManager.js';
|
||||
import { ChatCompressionService } from '../services/chatCompressionService.js';
|
||||
|
||||
import { TrackerService } from '../services/trackerService.js';
|
||||
import type { GenerateContentParameters } from '@google/genai';
|
||||
|
||||
@@ -155,6 +159,7 @@ import { CheckerRunner } from '../safety/checker-runner.js';
|
||||
import { ContextBuilder } from '../safety/context-builder.js';
|
||||
import { CheckerRegistry } from '../safety/registry.js';
|
||||
import { ConsecaSafetyChecker } from '../safety/conseca/conseca.js';
|
||||
import { ContinuityCompressionService } from '../services/continuityCompressionService.js'
|
||||
|
||||
export interface AccessibilitySettings {
|
||||
/** @deprecated Use ui.loadingPhrases instead. */
|
||||
@@ -507,6 +512,7 @@ export interface ConfigParameters {
|
||||
customIgnoreFilePaths?: string[];
|
||||
};
|
||||
checkpointing?: boolean;
|
||||
continuousSession?: boolean;
|
||||
proxy?: string;
|
||||
cwd: string;
|
||||
fileDiscoveryService?: FileDiscoveryService;
|
||||
@@ -663,6 +669,7 @@ export class Config implements McpContext {
|
||||
private fileDiscoveryService: FileDiscoveryService | null = null;
|
||||
private gitService: GitService | undefined = undefined;
|
||||
private readonly checkpointing: boolean;
|
||||
private readonly continuousSession: boolean;
|
||||
private readonly proxy: string | undefined;
|
||||
private readonly cwd: string;
|
||||
private readonly bugCommand: BugCommandSettings | undefined;
|
||||
@@ -798,6 +805,8 @@ export class Config implements McpContext {
|
||||
private readonly planModeRoutingEnabled: boolean;
|
||||
private readonly modelSteering: boolean;
|
||||
private contextManager?: ContextManager;
|
||||
private chatCompressionService?: ChatCompressionService;
|
||||
private continuityCompressionService?: ContinuityCompressionService;
|
||||
private terminalBackground: string | undefined = undefined;
|
||||
private remoteAdminSettings: AdminControlsSettings | undefined;
|
||||
private latestApiRequest: GenerateContentParameters | undefined;
|
||||
@@ -874,6 +883,7 @@ export class Config implements McpContext {
|
||||
customIgnoreFilePaths: params.fileFiltering?.customIgnoreFilePaths ?? [],
|
||||
};
|
||||
this.checkpointing = params.checkpointing ?? false;
|
||||
this.continuousSession = params.continuousSession ?? false;
|
||||
this.proxy = params.proxy;
|
||||
this.cwd = params.cwd ?? process.cwd();
|
||||
this.fileDiscoveryService = params.fileDiscoveryService ?? null;
|
||||
@@ -1198,6 +1208,8 @@ export class Config implements McpContext {
|
||||
await this.contextManager.refresh();
|
||||
}
|
||||
|
||||
this.chatCompressionService = new ChatCompressionService();
|
||||
|
||||
await this.geminiClient.initialize();
|
||||
this.initialized = true;
|
||||
}
|
||||
@@ -1897,6 +1909,22 @@ export class Config implements McpContext {
|
||||
return this.contextManager;
|
||||
}
|
||||
|
||||
getChatCompressionService(): ChatCompressionService {
|
||||
if (!this.chatCompressionService) {
|
||||
this.chatCompressionService = new ChatCompressionService();
|
||||
}
|
||||
return this.chatCompressionService;
|
||||
}
|
||||
|
||||
getContinuityCompressionService(): ContinuityCompressionService {
|
||||
if (!this.continuityCompressionService) {
|
||||
this.continuityCompressionService = new ContinuityCompressionService(
|
||||
this.getBaseLlmClient(),
|
||||
);
|
||||
}
|
||||
return this.continuityCompressionService;
|
||||
}
|
||||
|
||||
isJitContextEnabled(): boolean {
|
||||
return this.experimentalJitContext;
|
||||
}
|
||||
@@ -2196,6 +2224,10 @@ export class Config implements McpContext {
|
||||
return [];
|
||||
}
|
||||
|
||||
getContinuousSessionEnabled(): boolean {
|
||||
return this.continuousSession;
|
||||
}
|
||||
|
||||
getCheckpointingEnabled(): boolean {
|
||||
return this.checkpointing;
|
||||
}
|
||||
@@ -2843,6 +2875,12 @@ export class Config implements McpContext {
|
||||
maybeRegister(AskUserTool, () =>
|
||||
registry.registerTool(new AskUserTool(this.messageBus)),
|
||||
);
|
||||
maybeRegister(CheckpointStateTool, () =>
|
||||
registry.registerTool(new CheckpointStateTool(this, this.messageBus)),
|
||||
);
|
||||
maybeRegister(CompressTool, () =>
|
||||
registry.registerTool(new CompressTool(this, this.messageBus)),
|
||||
);
|
||||
if (this.getUseWriteTodos()) {
|
||||
maybeRegister(WriteTodosTool, () =>
|
||||
registry.registerTool(new WriteTodosTool(this.messageBus)),
|
||||
|
||||
@@ -39,6 +39,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -207,6 +212,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -494,6 +504,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -662,6 +677,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -830,6 +850,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -952,6 +977,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -1547,6 +1577,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -1711,6 +1746,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -1866,6 +1906,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -2021,6 +2066,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -2172,6 +2222,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -2323,6 +2378,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -2466,6 +2526,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -2616,6 +2681,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -3008,6 +3078,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -3159,6 +3234,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -3422,6 +3502,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -3573,6 +3658,11 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the \`checkpoint_state\` tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the \`compress\` tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in \`GEMINI.md\` files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
export enum AuthType {
|
||||
LOGIN_WITH_GOOGLE = 'oauth-personal',
|
||||
USE_GEMINI = 'gemini-api-key',
|
||||
USE_VERTEX_AI = 'vertex-ai',
|
||||
LEGACY_CLOUD_SHELL = 'cloud-shell',
|
||||
COMPUTE_ADC = 'compute-default-credentials',
|
||||
GATEWAY = 'gateway',
|
||||
}
|
||||
@@ -24,12 +24,14 @@ import {
|
||||
import { GeminiChat } from './geminiChat.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import {
|
||||
CompressionStatus,
|
||||
GeminiEventType,
|
||||
Turn,
|
||||
type ChatCompressionInfo,
|
||||
type ServerGeminiStreamEvent,
|
||||
} from './turn.js';
|
||||
import {
|
||||
CompressionStatus,
|
||||
type ChatCompressionInfo,
|
||||
} from './compression-status.js';
|
||||
import { getCoreSystemPrompt } from './prompts.js';
|
||||
import { DEFAULT_GEMINI_MODEL_AUTO } from '../config/models.js';
|
||||
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||
@@ -51,6 +53,7 @@ import * as policyCatalog from '../availability/policyCatalog.js';
|
||||
import { LlmRole, LoopType } from '../telemetry/types.js';
|
||||
import { partToString } from '../utils/partUtils.js';
|
||||
import { coreEvents } from '../utils/events.js';
|
||||
import { COMPRESS_TOOL_NAME } from '../tools/tool-names.js';
|
||||
|
||||
// Mock fs module to prevent actual file system operations during tests
|
||||
const mockFileSystem = new Map<string, string>();
|
||||
@@ -244,6 +247,13 @@ describe('Gemini Client (client.ts)', () => {
|
||||
getSkipNextSpeakerCheck: vi.fn().mockReturnValue(false),
|
||||
getShowModelInfoInChat: vi.fn().mockReturnValue(false),
|
||||
getContinueOnFailedApiCall: vi.fn(),
|
||||
getChatCompressionService: vi
|
||||
.fn()
|
||||
.mockReturnValue(new ChatCompressionService()),
|
||||
getContinuityCompressionService: vi.fn().mockResolvedValue({
|
||||
generateSnapshot: vi.fn().mockResolvedValue('Mock Snapshot'),
|
||||
}),
|
||||
getContinuousSessionEnabled: vi.fn().mockReturnValue(false),
|
||||
getProjectRoot: vi.fn().mockReturnValue('/test/project/root'),
|
||||
getIncludeDirectoryTree: vi.fn().mockReturnValue(true),
|
||||
storage: {
|
||||
@@ -251,6 +261,9 @@ describe('Gemini Client (client.ts)', () => {
|
||||
},
|
||||
getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
|
||||
getBaseLlmClient: vi.fn().mockReturnValue({
|
||||
generateContent: vi.fn().mockResolvedValue({
|
||||
candidates: [{ content: { parts: [{ text: '{"key": "value"}' }] } }],
|
||||
}),
|
||||
generateJson: vi.fn().mockResolvedValue({
|
||||
next_speaker: 'user',
|
||||
reasoning: 'test',
|
||||
@@ -390,11 +403,15 @@ describe('Gemini Client (client.ts)', () => {
|
||||
}));
|
||||
|
||||
client['chat'] = {
|
||||
getHistory: mockGetHistory,
|
||||
getHistory: mockGetHistory.mockReturnValue([]),
|
||||
addHistory: vi.fn(),
|
||||
setHistory: vi.fn(),
|
||||
setTools: vi.fn(),
|
||||
getLastPromptTokenCount: vi.fn(),
|
||||
getChatRecordingService: vi.fn().mockReturnValue({
|
||||
getConversation: vi.fn().mockReturnValue(null),
|
||||
getConversationFilePath: vi.fn().mockReturnValue(null),
|
||||
}),
|
||||
} as unknown as GeminiChat;
|
||||
});
|
||||
|
||||
@@ -3216,6 +3233,54 @@ ${JSON.stringify(
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('detects a manual compression request from the agent', async () => {
|
||||
// Arrange
|
||||
mockTurnRunFn.mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: 'content', value: 'Hello' };
|
||||
})(),
|
||||
);
|
||||
|
||||
vi.spyOn(ChatCompressionService.prototype, 'compress').mockResolvedValue({
|
||||
newHistory: [{ role: 'user', parts: [{ text: 'Summary' }] }],
|
||||
info: {
|
||||
originalTokenCount: 1000,
|
||||
newTokenCount: 500,
|
||||
compressionStatus: CompressionStatus.COMPRESSED,
|
||||
},
|
||||
});
|
||||
|
||||
const compressResponse = [
|
||||
{
|
||||
functionResponse: {
|
||||
name: COMPRESS_TOOL_NAME,
|
||||
response: { output: 'Compression requested.' },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// Act
|
||||
const stream = client.sendMessageStream(
|
||||
compressResponse,
|
||||
new AbortController().signal,
|
||||
'prompt-id-1',
|
||||
);
|
||||
|
||||
await fromAsync(stream);
|
||||
|
||||
// Assert
|
||||
// Verify that ChatCompressionService.compress was called with force=true
|
||||
expect(ChatCompressionService.prototype.compress).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
'prompt-id-1',
|
||||
false, // force
|
||||
'test-model',
|
||||
expect.anything(),
|
||||
false, // hasFailedCompressionAttempt
|
||||
);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateContent', () => {
|
||||
|
||||
@@ -18,12 +18,14 @@ import {
|
||||
getInitialChatHistory,
|
||||
} from '../utils/environmentContext.js';
|
||||
import {
|
||||
CompressionStatus,
|
||||
Turn,
|
||||
GeminiEventType,
|
||||
type ServerGeminiStreamEvent,
|
||||
type ChatCompressionInfo,
|
||||
} from './turn.js';
|
||||
import {
|
||||
CompressionStatus,
|
||||
type ChatCompressionInfo,
|
||||
} from './compression-status.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import { getCoreSystemPrompt } from './prompts.js';
|
||||
import { checkNextSpeaker } from '../utils/nextSpeakerChecker.js';
|
||||
@@ -42,7 +44,8 @@ import type {
|
||||
} from '../services/chatRecordingService.js';
|
||||
import type { ContentGenerator } from './contentGenerator.js';
|
||||
import { LoopDetectionService } from '../services/loopDetectionService.js';
|
||||
import { ChatCompressionService } from '../services/chatCompressionService.js';
|
||||
import type { ChatCompressionService } from '../services/chatCompressionService.js';
|
||||
import type { ContinuityCompressionService } from '../services/continuityCompressionService.js';
|
||||
import { ideContextStore } from '../ide/ideContext.js';
|
||||
import {
|
||||
logContentRetryFailure,
|
||||
@@ -92,7 +95,6 @@ export class GeminiClient {
|
||||
private sessionTurnCount = 0;
|
||||
|
||||
private readonly loopDetector: LoopDetectionService;
|
||||
private readonly compressionService: ChatCompressionService;
|
||||
private readonly toolOutputMaskingService: ToolOutputMaskingService;
|
||||
private lastPromptId: string;
|
||||
private currentSequenceModel: string | null = null;
|
||||
@@ -107,13 +109,20 @@ export class GeminiClient {
|
||||
|
||||
constructor(private readonly config: Config) {
|
||||
this.loopDetector = new LoopDetectionService(config);
|
||||
this.compressionService = new ChatCompressionService();
|
||||
this.toolOutputMaskingService = new ToolOutputMaskingService();
|
||||
this.lastPromptId = this.config.getSessionId();
|
||||
|
||||
coreEvents.on(CoreEvent.ModelChanged, this.handleModelChanged);
|
||||
}
|
||||
|
||||
get compressionService(): ChatCompressionService {
|
||||
return this.config.getChatCompressionService();
|
||||
}
|
||||
|
||||
get continuityCompressionService(): ContinuityCompressionService {
|
||||
return this.config.getContinuityCompressionService();
|
||||
}
|
||||
|
||||
private handleModelChanged = () => {
|
||||
this.currentSequenceModel = null;
|
||||
};
|
||||
@@ -735,6 +744,22 @@ export class GeminiClient {
|
||||
if (event.type === GeminiEventType.Error) {
|
||||
isError = true;
|
||||
}
|
||||
|
||||
if (event.type === GeminiEventType.ToolCallResponse) {
|
||||
const toolResponse = event.value;
|
||||
if (toolResponse.newHistory) {
|
||||
this.getChat().replaceHistory(toolResponse.newHistory);
|
||||
// Yield the event so UI knows compression happened
|
||||
yield {
|
||||
type: GeminiEventType.ChatCompressed,
|
||||
value: toolResponse.compressionInfo ?? {
|
||||
originalTokenCount: 0,
|
||||
newTokenCount: 0,
|
||||
compressionStatus: CompressionStatus.COMPRESSED,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loopDetectedAbort) {
|
||||
@@ -835,7 +860,8 @@ export class GeminiClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
return turn;
|
||||
const turnResult = turn;
|
||||
return turnResult;
|
||||
}
|
||||
|
||||
async *sendMessageStream(
|
||||
@@ -1116,6 +1142,7 @@ export class GeminiClient {
|
||||
this.hasFailedCompressionAttempt,
|
||||
);
|
||||
|
||||
|
||||
if (
|
||||
info.compressionStatus ===
|
||||
CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
export enum CompressionStatus {
|
||||
/** The compression was not necessary and no action was taken */
|
||||
NOOP,
|
||||
|
||||
/** The compression was successful */
|
||||
COMPRESSED,
|
||||
|
||||
/** The compression failed due to the compression inflating the token count */
|
||||
COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
||||
|
||||
/** The compression failed due to an error counting tokens */
|
||||
COMPRESSION_FAILED_TOKEN_COUNT_ERROR,
|
||||
|
||||
/** The compression failed because the summary was empty */
|
||||
COMPRESSION_FAILED_EMPTY_SUMMARY,
|
||||
|
||||
/** The compression was skipped due to previous failure, but content was truncated to budget */
|
||||
CONTENT_TRUNCATED,
|
||||
}
|
||||
|
||||
export interface ChatCompressionInfo {
|
||||
originalTokenCount: number;
|
||||
newTokenCount: number;
|
||||
compressionStatus: CompressionStatus;
|
||||
}
|
||||
@@ -261,6 +261,16 @@ export class GeminiChat {
|
||||
);
|
||||
}
|
||||
|
||||
private continuityAnchor?: string;
|
||||
|
||||
setContinuityAnchor(anchor: string) {
|
||||
this.continuityAnchor = anchor;
|
||||
}
|
||||
|
||||
getContinuityAnchor(): string | undefined {
|
||||
return this.continuityAnchor;
|
||||
}
|
||||
|
||||
setSystemInstruction(sysInstr: string) {
|
||||
this.systemInstruction = sysInstr;
|
||||
}
|
||||
@@ -687,17 +697,48 @@ export class GeminiChat {
|
||||
* @return History contents alternating between user and model for the entire
|
||||
* chat session.
|
||||
*/
|
||||
/**
|
||||
* Replaces the entire conversation history. Use with caution.
|
||||
* This is primarily used for context compression and history restoration.
|
||||
*/
|
||||
replaceHistory(newHistory: Content[]): void {
|
||||
validateHistory(newHistory);
|
||||
this.history = [...newHistory];
|
||||
this.lastPromptTokenCount = estimateTokenCountSync(
|
||||
this.history.flatMap((c) => c.parts || []),
|
||||
);
|
||||
}
|
||||
|
||||
getHistory(curated: boolean = false): Content[] {
|
||||
const history = curated
|
||||
? extractCuratedHistory(this.history)
|
||||
: this.history;
|
||||
// Return a shallow copy of the array to prevent callers from mutating
|
||||
// the internal history array (push/pop/splice). Content objects are
|
||||
// shared references — callers MUST NOT mutate them in place.
|
||||
// This replaces a prior structuredClone() which deep-copied the entire
|
||||
// conversation on every call, causing O(n) memory pressure per turn
|
||||
// that compounded into OOM crashes in long-running sessions.
|
||||
return [...history];
|
||||
|
||||
if (!this.continuityAnchor) {
|
||||
return [...history];
|
||||
}
|
||||
|
||||
const anchorText = `<state_checkpoint>\n${this.continuityAnchor}\n</state_checkpoint>`;
|
||||
const baseHistory = [...history];
|
||||
|
||||
if (baseHistory.length > 0 && baseHistory[0].role === 'user') {
|
||||
// Merge into the first user message to preserve role alternation
|
||||
const firstMessage = { ...baseHistory[0] };
|
||||
// Ensure we don't accidentally mutate the original parts array
|
||||
firstMessage.parts = [
|
||||
{ text: anchorText },
|
||||
...(firstMessage.parts || []),
|
||||
];
|
||||
baseHistory[0] = firstMessage;
|
||||
} else {
|
||||
// Prepend as a new user message
|
||||
baseHistory.unshift({
|
||||
role: 'user',
|
||||
parts: [{ text: anchorText }],
|
||||
});
|
||||
}
|
||||
|
||||
return baseHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
type ToolCallRequestInfo,
|
||||
type ToolCallResponseInfo,
|
||||
} from '../scheduler/types.js';
|
||||
import { type ChatCompressionInfo } from './compression-status.js';
|
||||
|
||||
export interface ServerTool {
|
||||
name: string;
|
||||
@@ -164,32 +165,6 @@ export type ServerGeminiErrorEvent = {
|
||||
value: GeminiErrorEventValue;
|
||||
};
|
||||
|
||||
export enum CompressionStatus {
|
||||
/** The compression was successful */
|
||||
COMPRESSED = 1,
|
||||
|
||||
/** The compression failed due to the compression inflating the token count */
|
||||
COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
||||
|
||||
/** The compression failed due to an error counting tokens */
|
||||
COMPRESSION_FAILED_TOKEN_COUNT_ERROR,
|
||||
|
||||
/** The compression failed because the summary was empty */
|
||||
COMPRESSION_FAILED_EMPTY_SUMMARY,
|
||||
|
||||
/** The compression was not necessary and no action was taken */
|
||||
NOOP,
|
||||
|
||||
/** The compression was skipped due to previous failure, but content was truncated to budget */
|
||||
CONTENT_TRUNCATED,
|
||||
}
|
||||
|
||||
export interface ChatCompressionInfo {
|
||||
originalTokenCount: number;
|
||||
newTokenCount: number;
|
||||
compressionStatus: CompressionStatus;
|
||||
}
|
||||
|
||||
export type ServerGeminiChatCompressedEvent = {
|
||||
type: GeminiEventType.ChatCompressed;
|
||||
value: ChatCompressionInfo | null;
|
||||
|
||||
@@ -39,6 +39,7 @@ export * from './core/logger.js';
|
||||
export * from './core/prompts.js';
|
||||
export * from './core/tokenLimits.js';
|
||||
export * from './core/turn.js';
|
||||
export * from './core/compression-status.js';
|
||||
export * from './core/geminiRequest.js';
|
||||
export * from './core/coreToolScheduler.js';
|
||||
export * from './scheduler/scheduler.js';
|
||||
@@ -118,6 +119,7 @@ export * from './services/fileDiscoveryService.js';
|
||||
export * from './services/gitService.js';
|
||||
export * from './services/FolderTrustDiscoveryService.js';
|
||||
export * from './services/chatRecordingService.js';
|
||||
export * from './services/chatCompressionService.js';
|
||||
export * from './services/fileSystemService.js';
|
||||
export * from './services/sessionSummaryUtils.js';
|
||||
export * from './services/contextManager.js';
|
||||
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
SHELL_TOOL_NAME,
|
||||
WRITE_FILE_TOOL_NAME,
|
||||
WRITE_TODOS_TOOL_NAME,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
COMPRESS_TOOL_NAME,
|
||||
GREP_PARAM_TOTAL_MAX_MATCHES,
|
||||
GREP_PARAM_INCLUDE_PATTERN,
|
||||
GREP_PARAM_EXCLUDE_PATTERN,
|
||||
@@ -206,6 +208,15 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
- **Navigating:** read the minimum required to not require additional turns spent reading the file.
|
||||
</examples>
|
||||
|
||||
## Intentional Continuity & Context Management
|
||||
- **Semantic Checkpointing:** Periodically use the ${formatToolName(
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
)} tool to "park" complex threads with high-fidelity summaries. This ensures that your technical rationale, discovered constraints, and progress are preserved with maximum signal during compression.
|
||||
- **Agentic Compression:** If you feel the context window is becoming cluttered or you have just finished a significant sub-task, use the ${formatToolName(
|
||||
COMPRESS_TOOL_NAME,
|
||||
)} tool to manually trigger a compression event. This clears the history while persisting your latest checkpoints.
|
||||
- **Context Awareness:** You are responsible for maintaining your context health. As history grows, technical noise (like long file reads or repetitive searches) creates **entropy** that degrades your reasoning precision and self-awareness. Signs of degradation include repeating redundant steps, circular reasoning, or experiencing subtle tool parameter errors. You MUST proactively use the "Save-Point" strategy: \`checkpoint_state\` to lock in critical progress and \`compress\` to restore clarity. It is always better to compress "too soon" than to struggle through a foggy context. Do not wait for an overflow; clear the deck as soon as a major sub-task is finished or noise begins to accumulate.
|
||||
|
||||
## Engineering Standards
|
||||
- **Contextual Precedence:** Instructions found in ${formattedFilenames} files are foundational mandates. They take absolute precedence over the general workflows and tool defaults described in this system prompt.
|
||||
- **Conventions & Style:** Rigorously adhere to existing workspace conventions, architectural patterns, and style (naming, formatting, typing, commenting). During the research phase, analyze surrounding files, tests, and configuration to ensure your changes are seamless, idiomatic, and consistent with the local context. Never compromise idiomatic quality or completeness (e.g., proper declarations, type safety, documentation) to minimize tool calls; all supporting changes required by local conventions are part of a surgical update.
|
||||
@@ -718,6 +729,8 @@ When the conversation history grows too large, you will be invoked to distill th
|
||||
|
||||
First, you will think through the entire history in a private <scratchpad>. Review the user's overall goal, the agent's actions, tool outputs, file modifications, and any unresolved questions. Identify every piece of information for future actions.
|
||||
|
||||
**AGENT CHECKPOINTS:** The history may contain one or more \`<state_checkpoint>\` blocks. These were explicitly written by the agent as high-fidelity hand-offs. You MUST prioritize the information in these checkpoints and ensure their technical details, rationale, and intent are preserved in your final snapshot.
|
||||
|
||||
After your reasoning is complete, generate the final <state_snapshot> XML object. Be incredibly dense with information. Omit any irrelevant conversational filler.
|
||||
|
||||
The structure MUST be as follows:
|
||||
|
||||
@@ -370,6 +370,8 @@ export class ToolExecutor {
|
||||
outputFile,
|
||||
contentLength: typeof content === 'string' ? content.length : undefined,
|
||||
data: toolResult.data,
|
||||
newHistory: toolResult.newHistory,
|
||||
compressionInfo: toolResult.compressionInfo,
|
||||
};
|
||||
|
||||
const startTime = 'startTime' in call ? call.startTime : undefined;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { Part } from '@google/genai';
|
||||
import type { Part, Content } from '@google/genai';
|
||||
import { type ChatCompressionInfo } from '../core/compression-status.js';
|
||||
import type {
|
||||
AnyDeclarativeTool,
|
||||
AnyToolInvocation,
|
||||
@@ -61,6 +62,17 @@ export interface ToolCallResponseInfo {
|
||||
* Optional data payload for passing structured information back to the caller.
|
||||
*/
|
||||
data?: Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* Optional new conversation history to replace the current one.
|
||||
* Used for context compression and history restoration.
|
||||
*/
|
||||
newHistory?: Content[];
|
||||
|
||||
/**
|
||||
* Optional compression metrics if the tool performed context compression.
|
||||
*/
|
||||
compressionInfo?: ChatCompressionInfo;
|
||||
}
|
||||
|
||||
/** Request to execute another tool immediately after a completed one. */
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
modelStringToModelConfigAlias,
|
||||
} from './chatCompressionService.js';
|
||||
import type { Content, GenerateContentResponse } from '@google/genai';
|
||||
import { CompressionStatus } from '../core/turn.js';
|
||||
import { CompressionStatus } from '../core/compression-status.js';
|
||||
import type { BaseLlmClient } from '../core/baseLlmClient.js';
|
||||
import type { GeminiChat } from '../core/geminiChat.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
import type { Content } from '@google/genai';
|
||||
import type { Config } from '../config/config.js';
|
||||
import type { GeminiChat } from '../core/geminiChat.js';
|
||||
import { type ChatCompressionInfo, CompressionStatus } from '../core/turn.js';
|
||||
import {
|
||||
type ChatCompressionInfo,
|
||||
CompressionStatus,
|
||||
} from '../core/compression-status.js';
|
||||
import { tokenLimit } from '../core/tokenLimits.js';
|
||||
import { getCompressionPrompt } from '../core/prompts.js';
|
||||
import { getResponseText } from '../utils/partUtils.js';
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { Content } from '@google/genai';
|
||||
import type { BaseLlmClient } from '../core/baseLlmClient.js';
|
||||
import { LlmRole } from '../telemetry/llmRole.js';
|
||||
import { getResponseText } from '../utils/partUtils.js';
|
||||
|
||||
/**
|
||||
* ContinuityCompressionService is a specialized summarizer for the "Mythical Continuous Session".
|
||||
*
|
||||
* Unlike the standard compression service which attempts to summarize the entire conversation,
|
||||
* this service prioritizes specific `<state_checkpoint>` blocks (Continuity Anchors)
|
||||
* provided by the agent. It ensures that critical intent and progress are preserved
|
||||
* with high fidelity while discarding "noisy" technical details (like large file reads)
|
||||
* that are no longer needed.
|
||||
*/
|
||||
export class ContinuityCompressionService {
|
||||
constructor(
|
||||
private readonly llmClient: BaseLlmClient,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generates a high-fidelity snapshot of the conversation state.
|
||||
* It specifically looks for the most recent checkpoint and uses it as the anchor.
|
||||
*/
|
||||
async generateSnapshot(history: Content[], model: string, promptId: string): Promise<string> {
|
||||
const prompt = `
|
||||
You are a context compression engine for a long-running software engineering session.
|
||||
Your goal is to produce a dense, high-fidelity <state_snapshot> that will replace the current history.
|
||||
|
||||
CRITICAL INSTRUCTIONS:
|
||||
1. Identify the most recent <state_checkpoint> in the history. This is the ground truth of the agent's progress.
|
||||
2. Incorporate any critical new information found *after* the last checkpoint.
|
||||
3. Remove all redundant tool outputs, file contents, and intermediate research steps.
|
||||
4. Output ONLY the new <state_snapshot> block.
|
||||
|
||||
Current History to compress:
|
||||
${JSON.stringify(history)}
|
||||
`.trim();
|
||||
|
||||
const result = await this.llmClient.generateContent({
|
||||
modelConfigKey: { model },
|
||||
contents: [{ role: 'user', parts: [{ text: prompt }] }],
|
||||
promptId,
|
||||
role: LlmRole.UTILITY_COMPRESSOR,
|
||||
abortSignal: new AbortController().signal
|
||||
});
|
||||
|
||||
return getResponseText(result)?.trim() ?? '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {
|
||||
BaseDeclarativeTool,
|
||||
BaseToolInvocation,
|
||||
Kind,
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
} from './tools.js';
|
||||
import {
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_PARAM_SUMMARY,
|
||||
} from './tool-names.js';
|
||||
import { CHECKPOINT_STATE_DEFINITION } from './definitions/coreTools.js';
|
||||
import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import type { GeminiChat } from '../core/geminiChat.js';
|
||||
|
||||
interface CheckpointStateParams {
|
||||
[CHECKPOINT_STATE_PARAM_SUMMARY]: string;
|
||||
}
|
||||
|
||||
class CheckpointStateInvocation extends BaseToolInvocation<
|
||||
CheckpointStateParams,
|
||||
ToolResult
|
||||
> {
|
||||
constructor(
|
||||
params: CheckpointStateParams,
|
||||
messageBus: MessageBus,
|
||||
toolName: string,
|
||||
toolDisplayName: string,
|
||||
private readonly chat: GeminiChat,
|
||||
) {
|
||||
super(params, messageBus, toolName, toolDisplayName);
|
||||
}
|
||||
|
||||
override getDescription(): string {
|
||||
return 'Parks the current state of the conversation with a high-fidelity summary.';
|
||||
}
|
||||
|
||||
override async execute(): Promise<ToolResult> {
|
||||
const summary = this.params[CHECKPOINT_STATE_PARAM_SUMMARY];
|
||||
const previousSummary = this.chat.getContinuityAnchor();
|
||||
|
||||
// Atomically update the chat session's continuity anchor.
|
||||
// This anchor will be used as a "hard hand-off" during the next compression event.
|
||||
this.chat.setContinuityAnchor(summary);
|
||||
|
||||
const llmContent = `<state_checkpoint>\n${summary}\n</state_checkpoint>\n\n${
|
||||
previousSummary
|
||||
? 'Previous checkpoint summary replaced. Use the `previous_summary` in the result data for reconciliation if needed.'
|
||||
: 'First checkpoint created. No previous summary found.'
|
||||
}`;
|
||||
|
||||
return {
|
||||
llmContent,
|
||||
returnDisplay: '',
|
||||
data: {
|
||||
previous_summary: previousSummary || null,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A tool that allows the agent to "park" a thread with a high-fidelity summary.
|
||||
*/
|
||||
export class CheckpointStateTool extends BaseDeclarativeTool<
|
||||
CheckpointStateParams,
|
||||
ToolResult
|
||||
> {
|
||||
static readonly Name = CHECKPOINT_STATE_TOOL_NAME;
|
||||
|
||||
constructor(
|
||||
private readonly config: Config,
|
||||
messageBus: MessageBus,
|
||||
) {
|
||||
super(
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
'CheckpointState',
|
||||
CHECKPOINT_STATE_DEFINITION.base.description ?? '',
|
||||
Kind.Think,
|
||||
CHECKPOINT_STATE_DEFINITION.base.parametersJsonSchema,
|
||||
messageBus,
|
||||
);
|
||||
}
|
||||
|
||||
override createInvocation(
|
||||
params: CheckpointStateParams,
|
||||
): ToolInvocation<CheckpointStateParams, ToolResult> {
|
||||
const chat = this.config.getGeminiClient().getChat();
|
||||
|
||||
return new CheckpointStateInvocation(
|
||||
params,
|
||||
this.messageBus,
|
||||
this.name,
|
||||
this.displayName,
|
||||
chat,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {
|
||||
BaseDeclarativeTool,
|
||||
BaseToolInvocation,
|
||||
Kind,
|
||||
type ToolInvocation,
|
||||
type ToolResult,
|
||||
} from './tools.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { COMPRESS_TOOL_NAME, COMPRESS_PARAM_FORCE } from './tool-names.js';
|
||||
import { COMPRESS_DEFINITION } from './definitions/coreTools.js';
|
||||
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';
|
||||
|
||||
interface CompressParams {
|
||||
[COMPRESS_PARAM_FORCE]?: boolean;
|
||||
}
|
||||
|
||||
class CompressInvocation extends BaseToolInvocation<
|
||||
CompressParams,
|
||||
ToolResult
|
||||
> {
|
||||
constructor(
|
||||
params: CompressParams,
|
||||
messageBus: MessageBus,
|
||||
toolName: string,
|
||||
toolDisplayName: string,
|
||||
private readonly config: Config,
|
||||
private readonly chat: GeminiChat,
|
||||
private readonly promptId: string,
|
||||
) {
|
||||
super(params, messageBus, toolName, toolDisplayName);
|
||||
}
|
||||
|
||||
override getDescription(): string {
|
||||
return 'Manually triggers a context compression event.';
|
||||
}
|
||||
|
||||
override async execute(): Promise<ToolResult> {
|
||||
const force = this.params[COMPRESS_PARAM_FORCE] !== false;
|
||||
|
||||
if (this.config.getContinuousSessionEnabled()) {
|
||||
const continuityService = await this.config.getContinuityCompressionService();
|
||||
const snapshot = await continuityService.generateSnapshot(
|
||||
this.chat.getHistory(),
|
||||
this.config.getModel(),
|
||||
this.promptId,
|
||||
);
|
||||
|
||||
const newHistory = [
|
||||
{
|
||||
role: 'user',
|
||||
parts: [{ text: snapshot }],
|
||||
},
|
||||
{
|
||||
role: 'model',
|
||||
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
||||
},
|
||||
];
|
||||
|
||||
this.chat.setContinuityAnchor('');
|
||||
|
||||
return {
|
||||
llmContent: `Compression completed. Status: 1`,
|
||||
returnDisplay: '',
|
||||
newHistory,
|
||||
compressionInfo: {
|
||||
originalTokenCount: 0,
|
||||
newTokenCount: 0,
|
||||
compressionStatus: CompressionStatus.COMPRESSED,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const { newHistory, info } = await this.config.getChatCompressionService().compress(
|
||||
this.chat,
|
||||
this.promptId,
|
||||
force,
|
||||
this.config.getModel(),
|
||||
this.config,
|
||||
false, // Manual compression
|
||||
);
|
||||
|
||||
if (newHistory) {
|
||||
return {
|
||||
llmContent: `Compression completed. Status: ${info.compressionStatus}`,
|
||||
returnDisplay: '',
|
||||
newHistory,
|
||||
compressionInfo: info,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
llmContent: `Compression failed. Status: ${info.compressionStatus}`,
|
||||
returnDisplay: `Context compression failed: ${info.compressionStatus}`,
|
||||
error: {
|
||||
message: `Context compression failed: ${info.compressionStatus}`,
|
||||
type: ToolErrorType.EXECUTION_FAILED,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A tool that allows the agent to manually trigger a context compression event.
|
||||
*/
|
||||
export class CompressTool extends BaseDeclarativeTool<
|
||||
CompressParams,
|
||||
ToolResult
|
||||
> {
|
||||
static readonly Name = COMPRESS_TOOL_NAME;
|
||||
|
||||
constructor(
|
||||
private readonly config: Config,
|
||||
messageBus: MessageBus,
|
||||
) {
|
||||
super(
|
||||
COMPRESS_TOOL_NAME,
|
||||
'Compress',
|
||||
COMPRESS_DEFINITION.base.description ?? '',
|
||||
Kind.Think,
|
||||
COMPRESS_DEFINITION.base.parametersJsonSchema,
|
||||
messageBus,
|
||||
);
|
||||
}
|
||||
|
||||
override createInvocation(
|
||||
params: CompressParams,
|
||||
): ToolInvocation<CompressParams, ToolResult> {
|
||||
const chat = this.config.getGeminiClient().getChat();
|
||||
const promptId = this.config.getSessionId(); // Best guess for current promptId in this context
|
||||
|
||||
return new CompressInvocation(
|
||||
params,
|
||||
this.messageBus,
|
||||
this.name,
|
||||
this.displayName,
|
||||
this.config,
|
||||
chat,
|
||||
promptId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -122,3 +122,11 @@ export const EXIT_PLAN_PARAM_PLAN_PATH = 'plan_path';
|
||||
// -- enter_plan_mode --
|
||||
export const ENTER_PLAN_MODE_TOOL_NAME = 'enter_plan_mode';
|
||||
export const PLAN_MODE_PARAM_REASON = 'reason';
|
||||
|
||||
// -- checkpoint_state --
|
||||
export const CHECKPOINT_STATE_TOOL_NAME = 'checkpoint_state';
|
||||
export const CHECKPOINT_STATE_PARAM_SUMMARY = 'summary';
|
||||
|
||||
// -- compress --
|
||||
export const COMPRESS_TOOL_NAME = 'compress';
|
||||
export const COMPRESS_PARAM_FORCE = 'force';
|
||||
|
||||
@@ -91,6 +91,10 @@ export {
|
||||
PLAN_MODE_PARAM_REASON,
|
||||
EXIT_PLAN_PARAM_PLAN_PATH,
|
||||
SKILL_PARAM_NAME,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_PARAM_SUMMARY,
|
||||
COMPRESS_TOOL_NAME,
|
||||
COMPRESS_PARAM_FORCE,
|
||||
} from './base-declarations.js';
|
||||
|
||||
// Re-export sets for compatibility
|
||||
@@ -221,6 +225,20 @@ export const ENTER_PLAN_MODE_DEFINITION: ToolDefinition = {
|
||||
overrides: (modelId) => getToolSet(modelId).enter_plan_mode,
|
||||
};
|
||||
|
||||
export const CHECKPOINT_STATE_DEFINITION: ToolDefinition = {
|
||||
get base() {
|
||||
return DEFAULT_LEGACY_SET.checkpoint_state;
|
||||
},
|
||||
overrides: (modelId) => getToolSet(modelId).checkpoint_state,
|
||||
};
|
||||
|
||||
export const COMPRESS_DEFINITION: ToolDefinition = {
|
||||
get base() {
|
||||
return DEFAULT_LEGACY_SET.compress;
|
||||
},
|
||||
overrides: (modelId) => getToolSet(modelId).compress,
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// DYNAMIC TOOL DEFINITIONS (LEGACY EXPORTS)
|
||||
// ============================================================================
|
||||
|
||||
@@ -73,6 +73,10 @@ import {
|
||||
ASK_USER_OPTION_PARAM_LABEL,
|
||||
ASK_USER_OPTION_PARAM_DESCRIPTION,
|
||||
PLAN_MODE_PARAM_REASON,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_PARAM_SUMMARY,
|
||||
COMPRESS_TOOL_NAME,
|
||||
COMPRESS_PARAM_FORCE,
|
||||
} from '../base-declarations.js';
|
||||
import {
|
||||
getShellDeclaration,
|
||||
@@ -734,4 +738,35 @@ The agent did not use the todo list because this task could be completed by a ti
|
||||
|
||||
exit_plan_mode: (plansDir) => getExitPlanModeDeclaration(plansDir),
|
||||
activate_skill: (skillNames) => getActivateSkillDeclaration(skillNames),
|
||||
|
||||
checkpoint_state: {
|
||||
name: CHECKPOINT_STATE_TOOL_NAME,
|
||||
description: `Parks the current state of the conversation with a high-fidelity summary provided by you. This summary will be preserved through future compression events, ensuring that critical intent, progress, and technical details are not lost. Use this tool when you have completed a significant sub-task or want to "save" the current context before it gets potentially compressed. Returns the previous summary (if any) to allow for reconciliation.`,
|
||||
parametersJsonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[CHECKPOINT_STATE_PARAM_SUMMARY]: {
|
||||
type: 'string',
|
||||
description:
|
||||
'A detailed, structured summary of the current session state, including goals, progress, constraints, and key discoveries.',
|
||||
},
|
||||
},
|
||||
required: [CHECKPOINT_STATE_PARAM_SUMMARY],
|
||||
},
|
||||
},
|
||||
|
||||
compress: {
|
||||
name: COMPRESS_TOOL_NAME,
|
||||
description: `Manually triggers a context compression event. Use this after calling '${CHECKPOINT_STATE_TOOL_NAME}' to ensure your summary is persisted and the context window is cleared of unnecessary details.`,
|
||||
parametersJsonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[COMPRESS_PARAM_FORCE]: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to force compression even if under the threshold.',
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -73,6 +73,10 @@ import {
|
||||
ASK_USER_OPTION_PARAM_LABEL,
|
||||
ASK_USER_OPTION_PARAM_DESCRIPTION,
|
||||
PLAN_MODE_PARAM_REASON,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_PARAM_SUMMARY,
|
||||
COMPRESS_TOOL_NAME,
|
||||
COMPRESS_PARAM_FORCE,
|
||||
} from '../base-declarations.js';
|
||||
import {
|
||||
getShellDeclaration,
|
||||
@@ -709,4 +713,35 @@ The agent did not use the todo list because this task could be completed by a ti
|
||||
|
||||
exit_plan_mode: (plansDir) => getExitPlanModeDeclaration(plansDir),
|
||||
activate_skill: (skillNames) => getActivateSkillDeclaration(skillNames),
|
||||
|
||||
checkpoint_state: {
|
||||
name: CHECKPOINT_STATE_TOOL_NAME,
|
||||
description: `Parks the current state of the conversation with a high-fidelity summary provided by you. This summary will be preserved through future compression events, ensuring that critical intent, progress, and technical details are not lost. Use this tool when you have completed a significant sub-task or want to "save" the current context before it gets potentially compressed. Returns the previous summary (if any) to allow for reconciliation.`,
|
||||
parametersJsonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[CHECKPOINT_STATE_PARAM_SUMMARY]: {
|
||||
type: 'string',
|
||||
description:
|
||||
'A detailed, structured summary of the current session state, including goals, progress, constraints, and key discoveries.',
|
||||
},
|
||||
},
|
||||
required: [CHECKPOINT_STATE_PARAM_SUMMARY],
|
||||
},
|
||||
},
|
||||
|
||||
compress: {
|
||||
name: COMPRESS_TOOL_NAME,
|
||||
description: `Manually triggers a context compression event. Use this after calling '${CHECKPOINT_STATE_TOOL_NAME}' to ensure your summary is persisted and the context window is cleared of unnecessary details.`,
|
||||
parametersJsonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[COMPRESS_PARAM_FORCE]: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to force compression even if under the threshold.',
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,4 +49,6 @@ export interface CoreToolSet {
|
||||
enter_plan_mode: FunctionDeclaration;
|
||||
exit_plan_mode: (plansDir: string) => FunctionDeclaration;
|
||||
activate_skill: (skillNames: string[]) => FunctionDeclaration;
|
||||
checkpoint_state: FunctionDeclaration;
|
||||
compress: FunctionDeclaration;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@ import {
|
||||
PLAN_MODE_PARAM_REASON,
|
||||
EXIT_PLAN_PARAM_PLAN_PATH,
|
||||
SKILL_PARAM_NAME,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_PARAM_SUMMARY,
|
||||
COMPRESS_TOOL_NAME,
|
||||
COMPRESS_PARAM_FORCE,
|
||||
} from './definitions/coreTools.js';
|
||||
|
||||
export {
|
||||
@@ -148,6 +152,10 @@ export {
|
||||
PLAN_MODE_PARAM_REASON,
|
||||
EXIT_PLAN_PARAM_PLAN_PATH,
|
||||
SKILL_PARAM_NAME,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_PARAM_SUMMARY,
|
||||
COMPRESS_TOOL_NAME,
|
||||
COMPRESS_PARAM_FORCE,
|
||||
};
|
||||
|
||||
export const LS_TOOL_NAME_LEGACY = 'list_directory'; // Just to be safe if anything used the old exported name directly
|
||||
@@ -229,6 +237,8 @@ export const ALL_BUILTIN_TOOL_NAMES = [
|
||||
GET_INTERNAL_DOCS_TOOL_NAME,
|
||||
ENTER_PLAN_MODE_TOOL_NAME,
|
||||
EXIT_PLAN_MODE_TOOL_NAME,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
COMPRESS_TOOL_NAME,
|
||||
] as const;
|
||||
|
||||
/**
|
||||
@@ -244,6 +254,8 @@ export const PLAN_MODE_TOOLS = [
|
||||
WEB_SEARCH_TOOL_NAME,
|
||||
ASK_USER_TOOL_NAME,
|
||||
ACTIVATE_SKILL_TOOL_NAME,
|
||||
CHECKPOINT_STATE_TOOL_NAME,
|
||||
COMPRESS_TOOL_NAME,
|
||||
] as const;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { FunctionDeclaration, PartListUnion } from '@google/genai';
|
||||
import type { Content, FunctionDeclaration, PartListUnion } from '@google/genai';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import type { DiffUpdateResult } from '../ide/ide-client.js';
|
||||
import type { ShellExecutionConfig } from '../services/shellExecutionService.js';
|
||||
@@ -595,6 +595,17 @@ export interface ToolResult {
|
||||
name: string;
|
||||
args: Record<string, unknown>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Optional new conversation history to replace the current one.
|
||||
* Used for context compression and history restoration.
|
||||
*/
|
||||
newHistory?: Content[];
|
||||
|
||||
/**
|
||||
* Optional compression metrics if the tool performed context compression.
|
||||
*/
|
||||
compressionInfo?: import('../core/compression-status.js').ChatCompressionInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
export const CONTINUITY_CHECKPOINT_TAG = 'state_checkpoint';
|
||||
export const CONTINUITY_SNAPSHOT_TAG = 'state_snapshot';
|
||||
@@ -292,6 +292,10 @@ function formatStructure(
|
||||
|
||||
// --- Main Exported Function ---
|
||||
|
||||
// --- Caching ---
|
||||
const structureCache = new Map<string, { result: string; timestamp: number }>();
|
||||
const CACHE_TTL_MS = 10000; // 10 seconds
|
||||
|
||||
/**
|
||||
* Generates a string representation of a directory's structure,
|
||||
* limiting the number of items displayed. Ignored folders are shown
|
||||
@@ -306,6 +310,14 @@ export async function getFolderStructure(
|
||||
options?: FolderStructureOptions,
|
||||
): Promise<string> {
|
||||
const resolvedPath = path.resolve(directory);
|
||||
const cacheKey = `${resolvedPath}:${JSON.stringify(options || {})}`;
|
||||
const now = Date.now();
|
||||
|
||||
const cached = structureCache.get(cacheKey);
|
||||
if (cached && now - cached.timestamp < CACHE_TTL_MS) {
|
||||
return cached.result;
|
||||
}
|
||||
|
||||
const mergedOptions: MergedFolderStructureOptions = {
|
||||
maxItems: options?.maxItems ?? MAX_ITEMS,
|
||||
ignoredFolders: options?.ignoredFolders ?? DEFAULT_IGNORED_FOLDERS,
|
||||
@@ -347,7 +359,9 @@ export async function getFolderStructure(
|
||||
summary += ` Folders or files indicated with ${TRUNCATION_INDICATOR} contain more items not shown, were ignored, or the display limit (${mergedOptions.maxItems} items) was reached.`;
|
||||
}
|
||||
|
||||
return `${summary}\n\n${resolvedPath}${path.sep}\n${structureLines.join('\n')}`;
|
||||
const finalResult = `${summary}\n\n${resolvedPath}${path.sep}\n${structureLines.join('\n')}`;
|
||||
structureCache.set(cacheKey, { result: finalResult, timestamp: now });
|
||||
return finalResult;
|
||||
} catch (error: unknown) {
|
||||
debugLogger.warn(
|
||||
`Error getting folder structure for ${resolvedPath}:`,
|
||||
|
||||
Reference in New Issue
Block a user