feat(memory): add daily log continuity controls

This commit is contained in:
William Valentin
2026-02-19 11:58:42 -08:00
parent 01cd726d7c
commit 290303c14e
10 changed files with 129 additions and 6 deletions
+50
View File
@@ -481,6 +481,56 @@ describe('AgentOrchestrator', () => {
expect(dailyLog).toContain('Log this turn');
expect(dailyLog).toContain('default response');
expect(dailyLog).toContain('tool_calls: 0');
expect(dailyLog).toContain('- session: unknown');
expect(dailyLog).toContain('- channel: unknown');
expect(dailyLog).toContain('- sender: unknown');
rmSync(tempDir, { recursive: true, force: true });
});
it('honors daily log truncation and metadata toggles', async () => {
const tempDir = mkdtempSync(join(tmpdir(), 'flynn-orchestrator-daily-log-config-'));
const memoryStore = new MemoryStore({ dir: tempDir, maxContextTokens: 2000 });
const session: Session = {
id: 'ws:test-user',
addMessage: vi.fn(),
getHistory: vi.fn(() => []),
clear: vi.fn(),
replaceHistory: vi.fn(),
getConfig: vi.fn(() => undefined),
setConfig: vi.fn(),
deleteConfig: vi.fn(),
};
const orchestrator = new AgentOrchestrator({
modelRouter: mockRouter,
systemPrompt: 'You are a helpful agent.',
primaryTier: 'default',
delegation: {
compaction: 'fast',
memory_extraction: 'default',
classification: 'complex',
tool_summarisation: 'default',
complex_reasoning: 'complex',
},
maxDelegationDepth: 10,
session,
memoryStore,
memoryDailyLogEnabled: true,
memoryDailyLogNamespacePrefix: 'daily',
memoryDailyLogIncludeSessionMetadata: false,
memoryDailyLogMaxUserChars: 120,
memoryDailyLogMaxAssistantChars: 150,
});
await orchestrator.process('x'.repeat(500));
const date = new Date().toISOString().slice(0, 10);
const dailyLog = memoryStore.read(`daily/${date}`);
expect(dailyLog).toContain('...[truncated]');
expect(dailyLog).not.toContain('- session:');
expect(dailyLog).not.toContain('- channel:');
expect(dailyLog).not.toContain('- sender:');
rmSync(tempDir, { recursive: true, force: true });
});
+22 -2
View File
@@ -140,6 +140,12 @@ export interface OrchestratorConfig {
memoryDailyLogEnabled?: boolean;
/** Namespace prefix for daily logs (full namespace: <prefix>/YYYY-MM-DD). */
memoryDailyLogNamespacePrefix?: string;
/** Include session/channel/sender metadata in each daily log block. */
memoryDailyLogIncludeSessionMetadata?: boolean;
/** Max chars stored from the user message in daily logs. */
memoryDailyLogMaxUserChars?: number;
/** Max chars stored from the assistant response in daily logs. */
memoryDailyLogMaxAssistantChars?: number;
/** Automatically retry failed primary runs on a higher tier. */
autoEscalate?: boolean;
/** Tier to try for auto-escalation retries. Defaults to complex. */
@@ -184,6 +190,9 @@ export class AgentOrchestrator {
private _memoryProactiveExtractNamespace: string;
private _memoryDailyLogEnabled: boolean;
private _memoryDailyLogNamespacePrefix: string;
private _memoryDailyLogIncludeSessionMetadata: boolean;
private _memoryDailyLogMaxUserChars: number;
private _memoryDailyLogMaxAssistantChars: number;
private _autoEscalate: boolean;
private _autoEscalateTier: ModelTier;
private _systemPromptBase: string;
@@ -213,6 +222,9 @@ export class AgentOrchestrator {
this._memoryProactiveExtractNamespace = config.memoryProactiveExtractNamespace ?? 'global';
this._memoryDailyLogEnabled = config.memoryDailyLogEnabled ?? false;
this._memoryDailyLogNamespacePrefix = config.memoryDailyLogNamespacePrefix ?? 'daily';
this._memoryDailyLogIncludeSessionMetadata = config.memoryDailyLogIncludeSessionMetadata ?? true;
this._memoryDailyLogMaxUserChars = Math.max(100, config.memoryDailyLogMaxUserChars ?? 2000);
this._memoryDailyLogMaxAssistantChars = Math.max(100, config.memoryDailyLogMaxAssistantChars ?? 4000);
this._autoEscalate = config.autoEscalate ?? false;
this._autoEscalateTier = config.autoEscalateTier ?? 'complex';
this._systemPromptBase = config.systemPrompt;
@@ -705,12 +717,20 @@ export class AgentOrchestrator {
const date = new Date().toISOString().slice(0, 10);
const timestamp = new Date().toISOString();
const namespace = `${this._memoryDailyLogNamespacePrefix}/${date}`;
const user = this._truncateForMemory(userMessage, 2000);
const assistant = this._truncateForMemory(assistantText, 4000);
const user = this._truncateForMemory(userMessage, this._memoryDailyLogMaxUserChars);
const assistant = this._truncateForMemory(assistantText, this._memoryDailyLogMaxAssistantChars);
const metadataLines = this._memoryDailyLogIncludeSessionMetadata
? [
`- session: ${this._session?.id ?? 'unknown'}`,
`- channel: ${this._agent.getToolPolicyContext()?.channel ?? 'unknown'}`,
`- sender: ${this._agent.getToolPolicyContext()?.sender ?? 'unknown'}`,
]
: [];
const block = [
`## ${timestamp}`,
'',
`- tool_calls: ${toolCallsInRun}`,
...metadataLines,
'',
'### User',
user,