/** * Session Manager — 다중 Antigravity CDP 세션을 관리 */ const CDPClient = require('./cdp-client'); class SessionManager { constructor() { /** @type {Map} */ this.sessions = new Map(); this.nextId = 1; } /** * 새 세션 등록 + CDP 연결 시도 */ async addSession(name, host = 'localhost', cdpPort = 9000) { const id = `s${this.nextId++}`; const client = new CDPClient(host, cdpPort); const session = { id, name, host, cdpPort, client, status: 'connecting', title: '', createdAt: new Date().toISOString(), }; this.sessions.set(id, session); // CDP 연결 시도 const result = await client.connect(); if (result.success) { session.status = 'connected'; session.title = result.title || ''; } else { session.status = 'error'; session.error = result.error; } // 연결 끊김 시 상태 업데이트 client.onDisconnect = () => { session.status = 'disconnected'; }; return session; } /** * 세션 제거 + CDP 연결 해제 */ async removeSession(id) { const session = this.sessions.get(id); if (!session) return false; await session.client.disconnect(); this.sessions.delete(id); return true; } /** * 세션 조회 */ getSession(id) { return this.sessions.get(id) || null; } /** * 전체 세션 목록 (클라이언트 전송용 직렬화) */ listSessions() { return Array.from(this.sessions.values()).map(s => ({ id: s.id, name: s.name, host: s.host, cdpPort: s.cdpPort, status: s.status, title: s.title, createdAt: s.createdAt, error: s.error || null, })); } /** * 세션 재연결 */ async reconnectSession(id) { const session = this.sessions.get(id); if (!session) return { success: false, error: 'Session not found' }; await session.client.disconnect(); const result = await session.client.connect(); if (result.success) { session.status = 'connected'; session.title = result.title || ''; session.error = null; } else { session.status = 'error'; session.error = result.error; } return result; } /** * 모든 세션 정리 */ async cleanup() { for (const [id] of this.sessions) { await this.removeSession(id); } } } module.exports = SessionManager;