refactor(memory): replace MemoryManagerAgent with prompt-driven memory editing across four tiers (#25716)

This commit is contained in:
Sandy Tao
2026-04-21 18:21:55 -07:00
committed by GitHub
parent ffb28c772b
commit 6edfba481f
24 changed files with 772 additions and 477 deletions
+34 -10
View File
@@ -41,7 +41,11 @@ import { EditTool } from '../tools/edit.js';
import { ShellTool } from '../tools/shell.js';
import { WriteFileTool } from '../tools/write-file.js';
import { WebFetchTool } from '../tools/web-fetch.js';
import { MemoryTool, setGeminiMdFilename } from '../tools/memoryTool.js';
import {
MemoryTool,
setGeminiMdFilename,
getCurrentGeminiMdFilename,
} from '../tools/memoryTool.js';
import { WebSearchTool } from '../tools/web-search.js';
import { AskUserTool } from '../tools/ask-user.js';
import { UpdateTopicTool } from '../tools/topicTool.js';
@@ -705,7 +709,7 @@ export interface ConfigParameters {
adminSkillsEnabled?: boolean;
experimentalJitContext?: boolean;
autoDistillation?: boolean;
experimentalMemoryManager?: boolean;
experimentalMemoryV2?: boolean;
experimentalAutoMemory?: boolean;
experimentalContextManagementConfig?: string;
experimentalAgentHistoryTruncation?: boolean;
@@ -950,7 +954,7 @@ export class Config implements McpContext, AgentLoopContext {
private disabledSkills: string[];
private readonly adminSkillsEnabled: boolean;
private readonly experimentalJitContext: boolean;
private readonly experimentalMemoryManager: boolean;
private readonly experimentalMemoryV2: boolean;
private readonly experimentalAutoMemory: boolean;
private readonly experimentalContextManagementConfig?: string;
private readonly memoryBoundaryMarkers: readonly string[];
@@ -1167,8 +1171,8 @@ export class Config implements McpContext, AgentLoopContext {
modelConfigServiceConfig ?? DEFAULT_MODEL_CONFIGS,
);
this.experimentalJitContext = params.experimentalJitContext ?? false;
this.experimentalMemoryManager = params.experimentalMemoryManager ?? false;
this.experimentalJitContext = params.experimentalJitContext ?? true;
this.experimentalMemoryV2 = params.experimentalMemoryV2 ?? false;
this.experimentalAutoMemory = params.experimentalAutoMemory ?? false;
this.experimentalContextManagementConfig =
params.experimentalContextManagementConfig;
@@ -2502,8 +2506,8 @@ export class Config implements McpContext, AgentLoopContext {
return this.memoryBoundaryMarkers;
}
isMemoryManagerEnabled(): boolean {
return this.experimentalMemoryManager;
isMemoryV2Enabled(): boolean {
return this.experimentalMemoryV2;
}
isAutoMemoryEnabled(): boolean {
@@ -3031,7 +3035,10 @@ export class Config implements McpContext, AgentLoopContext {
/**
* Checks if a given absolute path is allowed for file system operations.
* A path is allowed if it's within the workspace context or the project's temporary directory.
* A path is allowed if it's within the workspace context, the project's
* temporary directory, or is exactly the global personal `~/.gemini/GEMINI.md`
* file (the latter is the only file under `~/.gemini/` that is reachable —
* settings, credentials, keybindings, etc. remain disallowed).
*
* @param absolutePath The absolute path to check.
* @returns true if the path is allowed, false otherwise.
@@ -3046,8 +3053,25 @@ export class Config implements McpContext, AgentLoopContext {
const projectTempDir = this.storage.getProjectTempDir();
const resolvedTempDir = resolveToRealPath(projectTempDir);
if (isSubpath(resolvedTempDir, resolvedPath)) {
return true;
}
return isSubpath(resolvedTempDir, resolvedPath);
// Surgical allowlist: the global personal GEMINI.md file (and ONLY that
// file) is reachable so the prompt-driven memory flow can persist
// cross-project personal preferences. This deliberately does NOT
// allowlist the rest of `~/.gemini/`.
const globalMemoryFilePath = path.join(
Storage.getGlobalGeminiDir(),
getCurrentGeminiMdFilename(),
);
const resolvedGlobalMemoryFilePath =
resolveToRealPath(globalMemoryFilePath);
if (resolvedPath === resolvedGlobalMemoryFilePath) {
return true;
}
return false;
}
/**
@@ -3681,7 +3705,7 @@ export class Config implements McpContext, AgentLoopContext {
new ReadBackgroundOutputTool(this, this.messageBus),
),
);
if (!this.isMemoryManagerEnabled()) {
if (!this.isMemoryV2Enabled()) {
maybeRegister(MemoryTool, () =>
registry.registerTool(new MemoryTool(this.messageBus, this.storage)),
);