meezan / src /core /memory.ts
agenthinkmesh's picture
Upload project files
de07704 verified
Raw History Blame Contribute Delete
4.77 kB
// ==========================================
// MEEZAN - ميزان Memory System
// Persistent memory across all conversations
// ==========================================
import * as fs from 'fs';
import * as path from 'path';
import { UserProfile, ConversationHistory, Message, Language } from '../types';
interface Database {
users: Record<string, UserProfile>;
conversations: Record<string, ConversationHistory>;
version: string;
}
export class MemoryManager {
private dbPath: string;
private db: Database;
constructor(dbPath: string = './data/memory.json') {
this.dbPath = dbPath;
this.db = this.load();
}
private load(): Database {
const dir = path.dirname(this.dbPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
if (!fs.existsSync(this.dbPath)) {
const initial: Database = {
users: {},
conversations: {},
version: '1.0.0'
};
this.save(initial);
return initial;
}
try {
const content = fs.readFileSync(this.dbPath, 'utf-8');
return JSON.parse(content);
} catch {
console.error('Memory database corrupted, starting fresh');
return { users: {}, conversations: {}, version: '1.0.0' };
}
}
private save(data?: Database): void {
const toSave = data || this.db;
fs.writeFileSync(this.dbPath, JSON.stringify(toSave, null, 2), 'utf-8');
}
// ==========================================
// User Profile Management
// ==========================================
getUser(userId: string): UserProfile | null {
return this.db.users[userId] || null;
}
createUser(userId: string, language: Language = 'ar'): UserProfile {
const profile: UserProfile = {
id: userId,
language,
city: process.env.DEFAULT_CITY || 'Kuwait City',
country: process.env.DEFAULT_COUNTRY || 'Kuwait',
latitude: parseFloat(process.env.DEFAULT_LATITUDE || '29.3759'),
longitude: parseFloat(process.env.DEFAULT_LONGITUDE || '47.9774'),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
this.db.users[userId] = profile;
this.save();
return profile;
}
updateUser(userId: string, updates: Partial<UserProfile>): UserProfile {
const existing = this.getUser(userId) || this.createUser(userId);
const updated = {
...existing,
...updates,
updatedAt: new Date().toISOString()
};
this.db.users[userId] = updated;
this.save();
return updated;
}
getOrCreateUser(userId: string, language?: Language): UserProfile {
return this.getUser(userId) || this.createUser(userId, language);
}
// ==========================================
// Conversation History
// ==========================================
getHistory(userId: string): Message[] {
const conv = this.db.conversations[userId];
if (!conv) return [];
// Return last 20 messages for context window management
return conv.messages.slice(-20);
}
addMessage(userId: string, message: Message): void {
if (!this.db.conversations[userId]) {
this.db.conversations[userId] = {
userId,
messages: []
};
}
this.db.conversations[userId].messages.push(message);
// Keep only last 100 messages per user to prevent DB bloat
if (this.db.conversations[userId].messages.length > 100) {
this.db.conversations[userId].messages =
this.db.conversations[userId].messages.slice(-100);
}
this.save();
}
clearHistory(userId: string): void {
if (this.db.conversations[userId]) {
this.db.conversations[userId].messages = [];
this.save();
}
}
// ==========================================
// User Context Helpers
// ==========================================
setUserCity(userId: string, city: string, country: string, lat: number, lng: number): void {
this.updateUser(userId, { city, country, latitude: lat, longitude: lng });
}
setUserName(userId: string, name: string): void {
this.updateUser(userId, { name });
}
setUserLanguage(userId: string, language: Language): void {
this.updateUser(userId, { language });
}
setUserMadhab(userId: string, madhab: UserProfile['madhab']): void {
this.updateUser(userId, { madhab });
}
// ==========================================
// Stats
// ==========================================
getTotalUsers(): number {
return Object.keys(this.db.users).length;
}
getTotalMessages(): number {
return Object.values(this.db.conversations)
.reduce((sum, conv) => sum + conv.messages.length, 0);
}
}
export const memory = new MemoryManager(process.env.DB_PATH || './data/memory.json');