feat: add persistent memory system (Phase 2)

Implement file-based persistent memory with read/write/search tools:
- MemoryStore with namespace-scoped JSON storage
- memory-read, memory-write, memory-search builtin tools
- Auto-extraction of facts during context compaction
- Configurable via memory.enabled, memory.dir, memory.max_context_tokens
This commit is contained in:
William Valentin
2026-02-06 14:23:59 -08:00
parent 0180d4fb8f
commit 2e1071230a
6 changed files with 580 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
import type { Tool, ToolResult } from '../types.js';
import type { MemoryStore } from '../../memory/store.js';
interface MemoryReadArgs {
namespace: string;
}
/**
* Creates a memory.read tool bound to the given MemoryStore instance.
* Reads the full contents of a persistent memory namespace.
*/
export function createMemoryReadTool(store: MemoryStore): Tool {
return {
name: 'memory.read',
description:
'Read a persistent memory file by namespace. Available namespaces include "user" (user preferences and facts), "global" (cross-session knowledge), and session-specific namespaces. Returns the full contents of the memory file.',
inputSchema: {
type: 'object',
properties: {
namespace: {
type: 'string',
description: 'Memory namespace to read (e.g. "user", "global", "sessions/abc123")',
},
},
required: ['namespace'],
},
execute: async (rawArgs: unknown): Promise<ToolResult> => {
const args = rawArgs as MemoryReadArgs;
try {
const content = store.read(args.namespace);
if (!content) {
const namespaces = store.listNamespaces();
const available = namespaces.length > 0
? `Available namespaces: ${namespaces.join(', ')}`
: 'No namespaces exist yet.';
return {
success: true,
output: `Namespace "${args.namespace}" is empty or does not exist.\n${available}`,
};
}
return { success: true, output: content };
} catch (error) {
return {
success: false,
output: '',
error: error instanceof Error ? error.message : String(error),
};
}
},
};
}