gemini-cli/packages/cli/src/acp/commands/memory.ts
Sandy Tao 8573650253
Some checks failed
Testing: E2E (Chained) / Merge Queue Skipper (push) Has been cancelled
Testing: E2E (Chained) / download_repo_name (push) Has been cancelled
Testing: E2E (Chained) / Parse run context (push) Has been cancelled
Testing: E2E (Chained) / set_pending_status (push) Has been cancelled
Testing: E2E (Chained) / E2E Test (Linux) - sandbox:docker (push) Has been cancelled
Testing: E2E (Chained) / E2E Test (Linux) - sandbox:none (push) Has been cancelled
Testing: E2E (Chained) / E2E Test (macOS) (push) Has been cancelled
Testing: E2E (Chained) / Slow E2E - Win (push) Has been cancelled
Testing: E2E (Chained) / Evals (ALWAYS_PASSING) (push) Has been cancelled
Testing: E2E (Chained) / E2E (push) Has been cancelled
Testing: E2E (Chained) / set_workflow_status (push) Has been cancelled
Testing: CI / Merge Queue Skipper (push) Has been cancelled
Testing: CI / Lint (push) Has been cancelled
Testing: CI / Link Checker (push) Has been cancelled
Testing: CI / Test (Linux) - 20.x, cli (push) Has been cancelled
Testing: CI / Test (Linux) - 20.x, others (push) Has been cancelled
Testing: CI / Test (Linux) - 22.x, cli (push) Has been cancelled
Testing: CI / Test (Linux) - 22.x, others (push) Has been cancelled
Testing: CI / Test (Linux) - 24.x, cli (push) Has been cancelled
Testing: CI / Test (Linux) - 24.x, others (push) Has been cancelled
Testing: CI / Test (Mac) - 20.x, cli (push) Has been cancelled
Testing: CI / Test (Mac) - 20.x, others (push) Has been cancelled
Testing: CI / Test (Mac) - 22.x, cli (push) Has been cancelled
Testing: CI / Test (Mac) - 22.x, others (push) Has been cancelled
Testing: CI / Test (Mac) - 24.x, cli (push) Has been cancelled
Testing: CI / Test (Mac) - 24.x, others (push) Has been cancelled
Testing: CI / CodeQL (push) Has been cancelled
Testing: CI / Check Bundle Size (push) Has been cancelled
Testing: CI / Slow Test - Win - cli (push) Has been cancelled
Testing: CI / Slow Test - Win - others (push) Has been cancelled
Testing: CI / CI (push) Has been cancelled
Trigger Docs Rebuild / trigger-rebuild (push) Has been cancelled
Links / linkChecker (push) Has been cancelled
On Merge Smoke Test / smoke-test (push) Has been cancelled
feat(config): split memoryManager flag into autoMemory (#25601)
2026-04-18 00:08:02 +00:00

175 lines
4.9 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {
addMemory,
listInboxSkills,
listInboxPatches,
listMemoryFiles,
refreshMemory,
showMemory,
} from '@google/gemini-cli-core';
import type {
Command,
CommandContext,
CommandExecutionResponse,
} from './types.js';
const DEFAULT_SANITIZATION_CONFIG = {
allowedEnvironmentVariables: [],
blockedEnvironmentVariables: [],
enableEnvironmentVariableRedaction: false,
};
export class MemoryCommand implements Command {
readonly name = 'memory';
readonly description = 'Manage memory.';
readonly subCommands = [
new ShowMemoryCommand(),
new RefreshMemoryCommand(),
new ListMemoryCommand(),
new AddMemoryCommand(),
new InboxMemoryCommand(),
];
readonly requiresWorkspace = true;
async execute(
context: CommandContext,
_: string[],
): Promise<CommandExecutionResponse> {
return new ShowMemoryCommand().execute(context, _);
}
}
export class ShowMemoryCommand implements Command {
readonly name = 'memory show';
readonly description = 'Shows the current memory contents.';
async execute(
context: CommandContext,
_: string[],
): Promise<CommandExecutionResponse> {
const result = showMemory(context.agentContext.config);
return { name: this.name, data: result.content };
}
}
export class RefreshMemoryCommand implements Command {
readonly name = 'memory refresh';
readonly aliases = ['memory reload'];
readonly description = 'Refreshes the memory from the source.';
async execute(
context: CommandContext,
_: string[],
): Promise<CommandExecutionResponse> {
const result = await refreshMemory(context.agentContext.config);
return { name: this.name, data: result.content };
}
}
export class ListMemoryCommand implements Command {
readonly name = 'memory list';
readonly description = 'Lists the paths of the GEMINI.md files in use.';
async execute(
context: CommandContext,
_: string[],
): Promise<CommandExecutionResponse> {
const result = listMemoryFiles(context.agentContext.config);
return { name: this.name, data: result.content };
}
}
export class AddMemoryCommand implements Command {
readonly name = 'memory add';
readonly description = 'Add content to the memory.';
async execute(
context: CommandContext,
args: string[],
): Promise<CommandExecutionResponse> {
const textToAdd = args.join(' ').trim();
const result = addMemory(textToAdd);
if (result.type === 'message') {
return { name: this.name, data: result.content };
}
const toolRegistry = context.agentContext.toolRegistry;
const tool = toolRegistry.getTool(result.toolName);
if (tool) {
const abortController = new AbortController();
const signal = abortController.signal;
await context.sendMessage(`Saving memory via ${result.toolName}...`);
await tool.buildAndExecute(result.toolArgs, signal, undefined, {
shellExecutionConfig: {
sanitizationConfig: DEFAULT_SANITIZATION_CONFIG,
sandboxManager: context.agentContext.sandboxManager,
},
});
await refreshMemory(context.agentContext.config);
return {
name: this.name,
data: `Added memory: "${textToAdd}"`,
};
} else {
return {
name: this.name,
data: `Error: Tool ${result.toolName} not found.`,
};
}
}
}
export class InboxMemoryCommand implements Command {
readonly name = 'memory inbox';
readonly description =
'Lists skills extracted from past sessions that are pending review.';
async execute(
context: CommandContext,
_: string[],
): Promise<CommandExecutionResponse> {
if (!context.agentContext.config.isAutoMemoryEnabled()) {
return {
name: this.name,
data: 'The memory inbox requires Auto Memory. Enable it with: experimental.autoMemory = true in settings.',
};
}
const [skills, patches] = await Promise.all([
listInboxSkills(context.agentContext.config),
listInboxPatches(context.agentContext.config),
]);
if (skills.length === 0 && patches.length === 0) {
return { name: this.name, data: 'No items in inbox.' };
}
const lines: string[] = [];
for (const s of skills) {
const date = s.extractedAt
? ` (extracted: ${new Date(s.extractedAt).toLocaleDateString()})`
: '';
lines.push(`- **${s.name}**: ${s.description}${date}`);
}
for (const p of patches) {
const targets = p.entries.map((e) => e.targetPath).join(', ');
const date = p.extractedAt
? ` (extracted: ${new Date(p.extractedAt).toLocaleDateString()})`
: '';
lines.push(`- **${p.name}** (update): patches ${targets}${date}`);
}
const total = skills.length + patches.length;
return {
name: this.name,
data: `Memory inbox (${total}):\n${lines.join('\n')}`,
};
}
}