Files
gemini-cli/packages/core/src/services/memoryConsolidationService.test.ts
T
Sandy Tao 79ea865790 feat: introduce Forever Mode with A2A listener
- Sisyphus: auto-resume timer with schedule_work tool
- Confucius: built-in sub-agent for knowledge consolidation before compression
- Hippocampus: in-memory short-term memory via background micro-consolidation
- Bicameral Voice: proactive knowledge alignment on user input
- Archive compression mode for long-running sessions
- Onboarding dialog for first-time Forever Mode setup
- Refresh system instruction per turn so hippocampus reaches the model
- Auto-start A2A HTTP server when Forever Mode + Sisyphus enabled
- Bridge external messages into session and capture responses
- Display A2A port in status bar alongside Sisyphus timer
2026-03-06 22:03:20 -08:00

87 lines
2.6 KiB
TypeScript

/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { MemoryConsolidationService } from './memoryConsolidationService.js';
import type { Config } from '../config/config.js';
describe('MemoryConsolidationService', () => {
let mockConfig: Config;
let service: MemoryConsolidationService;
let mockGenerateContent: ReturnType<typeof vi.fn>;
let mockAppendHippocampusEntry: ReturnType<typeof vi.fn>;
beforeEach(() => {
vi.resetAllMocks();
mockGenerateContent = vi.fn().mockResolvedValue({
text: 'Mocked consolidated fact.',
});
mockAppendHippocampusEntry = vi.fn();
mockConfig = {
getIsForeverMode: vi.fn().mockReturnValue(true),
getBaseLlmClient: vi.fn().mockReturnValue({
generateContent: mockGenerateContent,
}),
appendHippocampusEntry: mockAppendHippocampusEntry,
} as unknown as Config;
service = new MemoryConsolidationService(mockConfig);
});
it('should not do anything if isForeverMode is false', () => {
vi.mocked(mockConfig.getIsForeverMode).mockReturnValue(false);
service.triggerMicroConsolidation([
{ role: 'user', parts: [{ text: 'test' }] },
]);
expect(mockGenerateContent).not.toHaveBeenCalled();
});
it('should not do anything if latestTurnContext is empty', () => {
service.triggerMicroConsolidation([]);
expect(mockGenerateContent).not.toHaveBeenCalled();
});
it('should trigger consolidation and append to in-memory hippocampus', async () => {
service.triggerMicroConsolidation([
{ role: 'user', parts: [{ text: 'test' }] },
]);
// Wait a tick for the fire-and-forget promise to resolve
await new Promise((resolve) => setTimeout(resolve, 0));
expect(mockGenerateContent).toHaveBeenCalledWith(
expect.objectContaining({
modelConfigKey: { model: 'gemini-3-flash-preview', isChatModel: false },
systemInstruction: expect.stringContaining(
'subconscious memory module',
),
}),
);
expect(mockAppendHippocampusEntry).toHaveBeenCalledWith(
expect.stringMatching(
/\[\d{2}:\d{2}:\d{2}\] - Mocked consolidated fact\.\n/,
),
);
});
it('should not append entry when model returns NO_SIGNIFICANT_FACTS', async () => {
mockGenerateContent.mockResolvedValue({
text: 'NO_SIGNIFICANT_FACTS',
});
service.triggerMicroConsolidation([
{ role: 'user', parts: [{ text: 'test' }] },
]);
await new Promise((resolve) => setTimeout(resolve, 0));
expect(mockAppendHippocampusEntry).not.toHaveBeenCalled();
});
});