UNPKG

contextual-agent-sdk

Version:

SDK for building AI agents with seamless voice-text context switching

215 lines 7.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MongoStorageProvider = void 0; const mongodb_1 = require("mongodb"); class MongoStorageProvider { client; db; collection; eventHandlers = new Set(); cleanupTimer; constructor(config) { if (!config.url) { throw new Error('MongoDB URL is required'); } this.client = new mongodb_1.MongoClient(config.url, { auth: config.username ? { username: config.username, password: config.password } : undefined, tls: config.ssl, tlsCertificateKeyFile: config.certPath, maxPoolSize: config.maxConnections, connectTimeoutMS: config.timeout }); this.initialize(config).catch(error => { this.emitEvent(this.createEvent('error', error)); }); } async initialize(config) { await this.client.connect(); this.db = this.client.db(); this.collection = this.db.collection('sessions'); await this.collection.createIndex({ userId: 1 }); await this.collection.createIndex({ 'lastActivity': 1 }, { expireAfterSeconds: 3600 }); if (config.cleanupInterval && config.maxAge) { this.cleanupTimer = setInterval(() => { this.cleanup(config.maxAge).catch(error => { this.emitEvent(this.createEvent('error', error)); }); }, config.cleanupInterval); } } async createSession(sessionId, session) { if (!this.collection) throw new Error('MongoDB not initialized'); const mongoSession = { ...session, _id: sessionId }; await this.collection.insertOne(mongoSession); this.emitEvent(this.createEvent('session_created', sessionId)); } async getSession(sessionId) { if (!this.collection) throw new Error('MongoDB not initialized'); const session = await this.collection.findOne({ _id: sessionId }); if (!session) return null; return this.convertDates(session); } async updateSession(sessionId, session) { if (!this.collection) throw new Error('MongoDB not initialized'); await this.collection.updateOne({ _id: sessionId }, { $set: session }); this.emitEvent(this.createEvent('session_updated', sessionId)); } async deleteSession(sessionId) { if (!this.collection) throw new Error('MongoDB not initialized'); const result = await this.collection.deleteOne({ _id: sessionId }); const deleted = result.deletedCount === 1; if (deleted) { this.emitEvent(this.createEvent('session_deleted', sessionId)); } return deleted; } async getSessions(filter) { if (!this.collection) throw new Error('MongoDB not initialized'); const query = this.buildMongoQuery(filter); const sessions = await this.collection.find(query).toArray(); return sessions.map(session => this.convertDates(session)); } async deleteSessions(filter) { if (!this.collection) throw new Error('MongoDB not initialized'); const query = this.buildMongoQuery(filter); const result = await this.collection.deleteMany(query); return result.deletedCount; } async cleanup(maxAge) { if (!this.collection) throw new Error('MongoDB not initialized'); this.emitEvent(this.createEvent('cleanup_started')); const result = await this.collection.deleteMany({ lastActivity: { $lt: new Date(Date.now() - maxAge) } }); this.emitEvent(this.createEvent('cleanup_completed', result.deletedCount)); } async healthCheck() { try { if (!this.db) return false; await this.db.command({ ping: 1 }); return true; } catch { return false; } } async getStats() { if (!this.collection) throw new Error('MongoDB not initialized'); const sessions = await this.getSessions(); const now = Date.now(); const oneDayAgo = now - 24 * 60 * 60 * 1000; const activeSessions = sessions.filter(s => s.lastActivity.getTime() > oneDayAgo); const durations = sessions.map(s => s.lastActivity.getTime() - s.startTime.getTime()); const avgDuration = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0; const modalityCount = sessions.reduce((acc, s) => { acc[s.currentModality]++; return acc; }, { text: 0, voice: 0 }); const storageSize = sessions.reduce((size, session) => { return size + JSON.stringify(session).length; }, 0); return { totalSessions: sessions.length, activeSessionsLast24h: activeSessions.length, averageSessionDuration: avgDuration, modalityDistribution: modalityCount, storageSize }; } on(handler) { this.eventHandlers.add(handler); } off(handler) { this.eventHandlers.delete(handler); } emitEvent(event) { this.eventHandlers.forEach(handler => handler(event)); } createEvent(type, data) { switch (type) { case 'session_created': case 'session_updated': case 'session_deleted': return { type, sessionId: data }; case 'cleanup_completed': return { type, deletedCount: data }; case 'error': return { type, error: data }; default: return { type }; } } buildMongoQuery(filter) { if (!filter) return {}; const query = {}; if (filter.userId) { query.userId = filter.userId; } if (filter.modality) { query.currentModality = filter.modality; } if (filter.startTime) { query.startTime = {}; if (filter.startTime.from) { query.startTime.$gte = filter.startTime.from; } if (filter.startTime.to) { query.startTime.$lte = filter.startTime.to; } } if (filter.lastActivity) { query.lastActivity = {}; if (filter.lastActivity.from) { query.lastActivity.$gte = filter.lastActivity.from; } if (filter.lastActivity.to) { query.lastActivity.$lte = filter.lastActivity.to; } } return query; } convertDates(session) { const { _id, ...sessionData } = session; return { ...sessionData, startTime: new Date(session.startTime), lastActivity: new Date(session.lastActivity), context: { ...session.context, memoryBank: session.context.memoryBank.map(memory => ({ ...memory, timestamp: new Date(memory.timestamp) })) } }; } async shutdown() { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); } await this.client.close(); } } exports.MongoStorageProvider = MongoStorageProvider; //# sourceMappingURL=MongoStorageProvider.js.map