lenzcom's picture
Upload folder using huggingface_hub
e706de2 verified
import fs from 'fs/promises';
import path from 'path';
import {fileURLToPath} from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export class MemoryManager {
constructor(memoryFileName = './memory.json') {
this.memoryFilePath = path.resolve(__dirname, memoryFileName);
}
async loadMemories() {
try {
const data = await fs.readFile(this.memoryFilePath, 'utf-8');
const json = JSON.parse(data);
// 🔧 Migrate old schema if needed
if (!json.memories) {
const upgraded = {memories: [], conversationHistory: []};
if (Array.isArray(json.facts)) {
for (const f of json.facts) {
upgraded.memories.push({
type: 'fact',
key: this.extractKey(f.content),
value: this.extractValue(f.content),
source: 'migration',
timestamp: f.timestamp || new Date().toISOString()
});
}
}
if (json.preferences && typeof json.preferences === 'object') {
for (const [key, val] of Object.entries(json.preferences)) {
upgraded.memories.push({
type: 'preference',
key,
value: this.extractValue(val),
source: 'migration',
timestamp: new Date().toISOString()
});
}
}
await this.saveMemories(upgraded);
return upgraded;
}
if (!Array.isArray(json.memories)) json.memories = [];
if (!Array.isArray(json.conversationHistory)) json.conversationHistory = [];
return json;
} catch {
return {memories: [], conversationHistory: []};
}
}
async saveMemories(memories) {
await fs.writeFile(this.memoryFilePath, JSON.stringify(memories, null, 2));
}
// Add or update memory without duplicates
async addMemory({type, key, value, source = 'user'}) {
const data = await this.loadMemories();
// Normalize for comparison
const normType = type.trim().toLowerCase();
const normKey = key.trim().toLowerCase();
const normValue = value.trim();
// Check if same key+type already exists
const existingIndex = data.memories.findIndex(
m => m.type === normType && m.key.toLowerCase() === normKey
);
if (existingIndex >= 0) {
const existing = data.memories[existingIndex];
// Update value if changed
if (existing.value !== normValue) {
existing.value = normValue;
existing.timestamp = new Date().toISOString();
existing.source = source;
console.log(`Updated memory: ${normKey}${normValue}`);
} else {
console.log(`Skipped duplicate memory: ${normKey}`);
}
} else {
// Add new memory
data.memories.push({
type: normType,
key: normKey,
value: normValue,
source,
timestamp: new Date().toISOString()
});
console.log(`Added memory: ${normKey} = ${normValue}`);
}
await this.saveMemories(data);
}
async getMemorySummary() {
const data = await this.loadMemories();
const facts = Array.isArray(data.memories)
? data.memories.filter(m => m.type === 'fact')
: [];
const prefs = Array.isArray(data.memories)
? data.memories.filter(m => m.type === 'preference')
: [];
let summary = "\n=== LONG-TERM MEMORY ===\n";
if (facts.length > 0) {
summary += "\nKnown Facts:\n";
for (const f of facts) summary += `- ${f.key}: ${f.value}\n`;
}
if (prefs.length > 0) {
summary += "\nUser Preferences:\n";
for (const p of prefs) summary += `- ${p.key}: ${p.value}\n`;
}
return summary;
}
extractKey(content) {
if (typeof content !== 'string') return 'unknown';
const [key] = content.split(':').map(s => s.trim());
return key || 'unknown';
}
extractValue(content) {
if (typeof content !== 'string') return '';
const parts = content.split(':').map(s => s.trim());
return parts.length > 1 ? parts.slice(1).join(':') : content;
}
}