import crypto from 'node:crypto'; import { MemoryItem } from '../types.js'; class MemoryStore { private items: Map = new Map(); constructor() { // Seed with initial self-hosting memory this.set({ key: 'system_welcome', value: { server: 'Do Everything API & MCP Server', mcpVersion: '2024-11-05', status: 'Online and ready for Agent connection.', }, tags: ['system', 'welcome', 'mcp'], agentId: 'system', }); } public set(params: { key: string; value: any; tags?: string[]; agentId?: string; ttlSeconds?: number; }): MemoryItem { const existing = this.items.get(params.key); const now = new Date().toISOString(); const item: MemoryItem = { id: existing ? existing.id : crypto.randomUUID(), key: params.key, value: params.value, tags: params.tags || (existing ? existing.tags : []), agentId: params.agentId || (existing ? existing.agentId : 'agent'), createdAt: existing ? existing.createdAt : now, updatedAt: now, ttlSeconds: params.ttlSeconds, }; this.items.set(params.key, item); return item; } public get(key: string): MemoryItem | null { const item = this.items.get(key); if (!item) return null; // Check TTL expiration if (item.ttlSeconds) { const created = new Date(item.updatedAt).getTime(); if (Date.now() - created > item.ttlSeconds * 1000) { this.items.delete(key); return null; } } return item; } public delete(key: string): boolean { return this.items.delete(key); } public list(tagFilter?: string, limit = 50): MemoryItem[] { let result = Array.from(this.items.values()); if (tagFilter) { result = result.filter(item => item.tags.some(t => t.toLowerCase() === tagFilter.toLowerCase())); } result.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()); return result.slice(0, limit); } public search(query?: string, tag?: string): MemoryItem[] { let result = Array.from(this.items.values()); if (tag) { result = result.filter(item => item.tags.includes(tag)); } if (query && query.trim().length > 0) { const q = query.toLowerCase(); result = result.filter(item => { const keyMatch = item.key.toLowerCase().includes(q); const valMatch = JSON.stringify(item.value).toLowerCase().includes(q); const tagMatch = item.tags.some(t => t.toLowerCase().includes(q)); return keyMatch || valMatch || tagMatch; }); } return result; } public count(): number { return this.items.size; } public clear(): void { this.items.clear(); } } export const memoryStore = new MemoryStore();