Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/cli/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ they appear in the UI.
| Model Steering | `experimental.modelSteering` | Enable model steering (user hints) to guide the model during tool execution. | `false` |
| Direct Web Fetch | `experimental.directWebFetch` | Enable web fetch behavior that bypasses LLM summarization. | `false` |
| Memory Manager Agent | `experimental.memoryManager` | Replace the built-in save_memory tool with a memory manager subagent that supports adding, removing, de-duplicating, and organizing memories. | `false` |
| Use the power user profile for massive contexts. | `experimental.powerUserProfile` | Enables continuous minimal GC near the max tokens limit instead of a blocked backbuffer. | `false` |
| Use the generalist profile to manage agent contexts. | `experimental.generalistProfile` | Suitable for general coding and software development tasks. | `false` |
| Enable Context Management | `experimental.contextManagement` | Enable logic for context management. | `false` |
| Topic & Update Narration | `experimental.topicUpdateNarration` | Enable the experimental Topic & Update communication model for reduced chattiness and structured progress reporting. | `false` |
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,12 @@ their corresponding top-level category object in your `settings.json` file.
- **Default:** `false`
- **Requires restart:** Yes

- **`experimental.powerUserProfile`** (boolean):
- **Description:** Enables continuous minimal GC near the max tokens limit
instead of a blocked backbuffer.
- **Default:** `false`
- **Requires restart:** Yes

- **`experimental.generalistProfile`** (boolean):
- **Description:** Suitable for general coding and software development tasks.
- **Default:** `false`
Expand Down
31 changes: 13 additions & 18 deletions packages/cli/src/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
type MCPServerConfig,
type GeminiCLIExtension,
Storage,
generalistProfile,
GENERALIST_PROFILE,
type ContextManagementConfig,
} from '@google/gemini-cli-core';
import { loadCliConfig, parseArguments, type CliArgs } from './config.js';
Expand Down Expand Up @@ -2211,7 +2211,7 @@ describe('loadCliConfig context management', () => {
});
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getContextManagementConfig()).toStrictEqual(
generalistProfile,
GENERALIST_PROFILE,
);
expect(config.isContextManagementEnabled()).toBe(true);
});
Expand All @@ -2220,24 +2220,19 @@ describe('loadCliConfig context management', () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments(createTestMergedSettings());
const contextManagementConfig: Partial<ContextManagementConfig> = {
historyWindow: {
budget: {
maxPressureStrategy: 'truncate',
maxTokens: 100_000,
retainedTokens: 50_000,
},
messageLimits: {
normalMaxTokens: 1000,
retainedMaxTokens: 10_000,
normalizationHeadRatio: 0.25,
},
tools: {
distillation: {
maxOutputTokens: 10_000,
summarizationThresholdTokens: 15_000,
},
outputMasking: {
protectionThresholdTokens: 30_000,
minPrunableThresholdTokens: 10_000,
protectLatestTurn: false,
protectedEpisodes: 1,
protectSystemEpisode: true,
},
strategies: {
historySquashing: { maxTokensPerNode: 12000 },
toolMasking: { stringLengthThresholdTokens: 10000 },
semanticCompression: {
nodeThresholdTokens: 5000,
compressionModel: 'chat-compression-2.5-flash-lite',
},
},
};
Expand Down
13 changes: 10 additions & 3 deletions packages/cli/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ import {
type HookEventName,
type OutputFormat,
detectIdeFromEnv,
generalistProfile,
GENERALIST_PROFILE,
POWER_USER_PROFILE,
STRESS_TEST_PROFILE,
} from '@google/gemini-cli-core';
import {
type Settings,
Expand Down Expand Up @@ -886,12 +888,17 @@ export async function loadCliConfig(

const useGeneralistProfile =
settings.experimental?.generalistProfile ?? false;
const useStressTestProfile = settings.experimental?.stressTestProfile ?? false;
const usePowerUserProfile = settings.experimental?.powerUserProfile ?? false;
const useContextManagement =
settings.experimental?.contextManagement ?? false;
const contextManagement = {
...(useGeneralistProfile ? generalistProfile : {}),
...(useGeneralistProfile ? GENERALIST_PROFILE : {}),
...(usePowerUserProfile ? POWER_USER_PROFILE : {}),
...(useStressTestProfile ? STRESS_TEST_PROFILE : {}),
...(useContextManagement ? settings?.contextManagement : {}),
enabled: useContextManagement || useGeneralistProfile,
enabled:
useContextManagement || useGeneralistProfile || usePowerUserProfile || useStressTestProfile,
};

return new Config({
Expand Down
49 changes: 49 additions & 0 deletions packages/cli/src/config/settingsSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2149,6 +2149,26 @@ const SETTINGS_SCHEMA = {
'Replace the built-in save_memory tool with a memory manager subagent that supports adding, removing, de-duplicating, and organizing memories.',
showInDialog: true,
},
powerUserProfile: {
type: 'boolean',
label: 'Use the power user profile for massive contexts.',
category: 'Experimental',
requiresRestart: true,
default: false,
description:
'Enables continuous minimal GC near the max tokens limit instead of a blocked backbuffer.',
showInDialog: true,
},
stressTestProfile: {
type: 'boolean',
label: 'Stress Test Profile (Context GC)',
category: 'Experimental',
requiresRestart: true,
default: false,
description:
'Aggressively limits the token budget (6k retained, 12k max) to force rapid background snapshotting and foreground truncations for local E2E testing of the context system.',
showInDialog: true,
},
generalistProfile: {
type: 'boolean',
label: 'Use the generalist profile to manage agent contexts.',
Expand Down Expand Up @@ -2462,6 +2482,35 @@ const SETTINGS_SCHEMA = {
default: {},
showInDialog: false,
properties: {
maxPressureStrategy: {
type: 'string',
label: 'Max Pressure Strategy',
category: 'Context Management',
requiresRestart: true,
default: 'truncate',
description: 'Action to take when hitting the synchronous token ceiling.',
showInDialog: false,
enum: ['truncate', 'compress', 'rollingSummarizer'],
},
gcTarget: {
type: 'string',
label: 'GC Target',
category: 'Context Management',
requiresRestart: true,
default: 'incremental',
description: 'The target floor for synchronous context shedding.',
showInDialog: false,
enum: ['incremental', 'freeNTokens', 'max'],
},
freeTokensTarget: {
type: 'number',
label: 'Free Tokens Target',
category: 'Context Management',
requiresRestart: true,
default: undefined,
description: 'Amount of tokens to free when gcTarget is freeNTokens.',
showInDialog: false,
},
maxTokens: {
type: 'number',
label: 'Max Tokens',
Expand Down
122 changes: 22 additions & 100 deletions packages/core/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ import { inspect } from 'node:util';
import process from 'node:process';
import { z } from 'zod';
import type { ConversationRecord } from '../services/chatRecordingService.js';
import type {
AgentHistoryProviderConfig,
ContextManagementConfig,
ToolOutputMaskingConfig,
} from '../context/types.js';
import type { ContextManagementConfig } from '../context/types.js';
export type { ConversationRecord };
import {
AuthType,
Expand Down Expand Up @@ -436,12 +432,6 @@ import {
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
type FileFilteringOptions,
} from './constants.js';
import {
DEFAULT_TOOL_PROTECTION_THRESHOLD,
DEFAULT_MIN_PRUNABLE_TOKENS_THRESHOLD,
DEFAULT_PROTECT_LATEST_TURN,
} from '../context/toolOutputMaskingService.js';

import {
type ExtensionLoader,
SimpleExtensionLoader,
Expand Down Expand Up @@ -1139,40 +1129,30 @@ export class Config implements McpContext, AgentLoopContext {
this.memoryBoundaryMarkers = params.memoryBoundaryMarkers ?? ['.git'];
this.contextManagement = {
enabled: params.contextManagement?.enabled ?? false,
historyWindow: {
maxTokens: params.contextManagement?.historyWindow?.maxTokens ?? 150000,
budget: {
maxTokens: params.contextManagement?.budget?.maxTokens ?? 150000,
retainedTokens:
params.contextManagement?.historyWindow?.retainedTokens ?? 40000,
params.contextManagement?.budget?.retainedTokens ?? 40000,
gcTarget: params.contextManagement?.budget?.gcTarget ?? 'incremental',
freeTokensTarget: params.contextManagement?.budget?.freeTokensTarget ?? undefined,
maxPressureStrategy: params.contextManagement?.budget?.maxPressureStrategy ?? 'truncate',
},
messageLimits: {
normalMaxTokens:
params.contextManagement?.messageLimits?.normalMaxTokens ?? 2500,
retainedMaxTokens:
params.contextManagement?.messageLimits?.retainedMaxTokens ?? 12000,
normalizationHeadRatio:
params.contextManagement?.messageLimits?.normalizationHeadRatio ??
0.25,
},
tools: {
distillation: {
maxOutputTokens:
params.contextManagement?.tools?.distillation?.maxOutputTokens ??
10000,
summarizationThresholdTokens:
params.contextManagement?.tools?.distillation
?.summarizationThresholdTokens ?? 20000,
strategies: {
historySquashing: {
maxTokensPerNode:
params.contextManagement?.strategies?.historySquashing
?.maxTokensPerNode ?? 3000,
},
toolMasking: {
stringLengthThresholdTokens:
params.contextManagement?.strategies?.toolMasking
?.stringLengthThresholdTokens ?? 10000,
},
outputMasking: {
protectionThresholdTokens:
params.contextManagement?.tools?.outputMasking
?.protectionThresholdTokens ?? DEFAULT_TOOL_PROTECTION_THRESHOLD,
minPrunableThresholdTokens:
params.contextManagement?.tools?.outputMasking
?.minPrunableThresholdTokens ??
DEFAULT_MIN_PRUNABLE_TOKENS_THRESHOLD,
protectLatestTurn:
params.contextManagement?.tools?.outputMasking?.protectLatestTurn ??
DEFAULT_PROTECT_LATEST_TURN,
semanticCompression: {
nodeThresholdTokens:
params.contextManagement?.strategies?.semanticCompression
?.nodeThresholdTokens ?? 5000,

},
},
};
Expand Down Expand Up @@ -2391,18 +2371,6 @@ export class Config implements McpContext, AgentLoopContext {
return this.contextManagement;
}

get agentHistoryProviderConfig(): AgentHistoryProviderConfig {
return {
maxTokens: this.contextManagement.historyWindow.maxTokens,
retainedTokens: this.contextManagement.historyWindow.retainedTokens,
normalMessageTokens: this.contextManagement.messageLimits.normalMaxTokens,
maximumMessageTokens:
this.contextManagement.messageLimits.retainedMaxTokens,
normalizationHeadRatio:
this.contextManagement.messageLimits.normalizationHeadRatio,
};
}

isTopicUpdateNarrationEnabled(): boolean {
return this.topicUpdateNarration;
}
Expand All @@ -2411,43 +2379,6 @@ export class Config implements McpContext, AgentLoopContext {
return this.modelSteering;
}

async getToolOutputMaskingConfig(): Promise<ToolOutputMaskingConfig> {
await this.ensureExperimentsLoaded();

const remoteProtection =
this.experiments?.flags[ExperimentFlags.MASKING_PROTECTION_THRESHOLD]
?.intValue;
const remotePrunable =
this.experiments?.flags[ExperimentFlags.MASKING_PRUNABLE_THRESHOLD]
?.intValue;
const remoteProtectLatest =
this.experiments?.flags[ExperimentFlags.MASKING_PROTECT_LATEST_TURN]
?.boolValue;

const parsedProtection = remoteProtection
? parseInt(remoteProtection, 10)
: undefined;
const parsedPrunable = remotePrunable
? parseInt(remotePrunable, 10)
: undefined;

return {
protectionThresholdTokens:
parsedProtection !== undefined && !isNaN(parsedProtection)
? parsedProtection
: this.contextManagement.tools.outputMasking
.protectionThresholdTokens,
minPrunableThresholdTokens:
parsedPrunable !== undefined && !isNaN(parsedPrunable)
? parsedPrunable
: this.contextManagement.tools.outputMasking
.minPrunableThresholdTokens,
protectLatestTurn:
remoteProtectLatest ??
this.contextManagement.tools.outputMasking.protectLatestTurn,
};
}

getGeminiMdFileCount(): number {
if (this.experimentalJitContext && this.memoryContextManager) {
return this.memoryContextManager.getLoadedPaths().size;
Expand Down Expand Up @@ -3298,15 +3229,6 @@ export class Config implements McpContext, AgentLoopContext {
);
}

getToolMaxOutputTokens(): number {
return this.contextManagement.tools.distillation.maxOutputTokens;
}

getToolSummarizationThresholdTokens(): number {
return this.contextManagement.tools.distillation
.summarizationThresholdTokens;
}

getNextCompressionTruncationId(): number {
return ++this.compressionTruncationCounter;
}
Expand Down
Loading
Loading