diff --git a/plugins/matrix-plugin/index.ts b/plugins/matrix-plugin/index.ts index 6a18ed2..37d3727 100644 --- a/plugins/matrix-plugin/index.ts +++ b/plugins/matrix-plugin/index.ts @@ -36,8 +36,6 @@ async function runPlugin(ctx: any, options: any, sdkClient?: any) { log(`Configuration loaded`) - const sessionRetentionMs = 30 * 60 * 1000 - const matrix = new MatrixBotClient(options) const sessionManager = new SessionManager(options.rateLimitSeconds || 5) @@ -289,10 +287,7 @@ async function runPlugin(ctx: any, options: any, sdkClient?: any) { } }) - // Session expiry loop - expiryInterval = sessionManager.startExpiryLoop(sessionRetentionMs) - - // V2 Storage - defensive access + // Start Matrix client if (isV2 && ctx?.storage) { await ctx.storage.set("matrix/plugin_version", "1.0.0") await ctx.storage.set("matrix/started_at", new Date().toISOString()) @@ -306,7 +301,6 @@ async function runPlugin(ctx: any, options: any, sdkClient?: any) { cleanup = () => { log("Plugin cleaning up...") eventController.abort() - if (expiryInterval) clearInterval(expiryInterval) matrix.stop() } diff --git a/plugins/matrix-plugin/session-manager.ts b/plugins/matrix-plugin/session-manager.ts index 897437a..627e587 100644 --- a/plugins/matrix-plugin/session-manager.ts +++ b/plugins/matrix-plugin/session-manager.ts @@ -21,6 +21,7 @@ export function encodeSessionId(matrixRoomId: string, threadRootId: string): str } const SESSION_MAP_FILE = path.join(process.env.HOME || "/tmp", ".opencode-matrix-sessions.json") +console.log(`[SessionManager] SESSION_MAP_FILE=${SESSION_MAP_FILE}`) interface SessionMapEntry { matrixRoomId: string @@ -37,15 +38,18 @@ function loadSessionMap(): Map { try { if (fs.existsSync(SESSION_MAP_FILE)) { const data = JSON.parse(fs.readFileSync(SESSION_MAP_FILE, "utf-8")) + console.log(`[SessionManager] Loaded ${data.length} sessions from ${SESSION_MAP_FILE}`) if (Array.isArray(data)) { for (const entry of data) { const key = `${entry.matrixRoomId}::${entry.threadRootId}` result.set(key, entry) } } + } else { + console.log(`[SessionManager] File not found: ${SESSION_MAP_FILE}`) } } catch (e) { - // ignore + console.log(`[SessionManager] Error loading: ${e}`) } return result } @@ -166,25 +170,6 @@ export class SessionManager { return false } - expireInactive(maxAgeMs: number): void { - const now = Date.now() - for (const [sessionId, session] of this.sessions) { - if (now - session.lastActivity > maxAgeMs) { - const key = sessionId - this.sessions.delete(key) - this.persistentMap.delete(key) - this.activeQueries.delete(key) - } - } - saveSessionMap(this.persistentMap) - } - - startExpiryLoop(maxAgeMs: number, intervalMs: number = 60000): NodeJS.Timeout { - return setInterval(() => { - this.expireInactive(maxAgeMs) - }, intervalMs) - } - saveSession(matrixRoomId: string, threadRootId: string, opencodeSessionId: string): void { const key = this.getSessionKey(matrixRoomId, threadRootId) const session = this.sessions.get(key) @@ -202,4 +187,21 @@ export class SessionManager { saveSessionMap(this.persistentMap) } } + + syncWithOpenCode(openCodeSessionIds: Set): void { + const toDelete: string[] = [] + for (const [, entry] of this.persistentMap) { + if (!openCodeSessionIds.has(entry.opencodeSessionId)) { + toDelete.push(`${entry.matrixRoomId}::${entry.threadRootId}`) + } + } + for (const key of toDelete) { + this.persistentMap.delete(key) + this.sessions.delete(key) + this.activeQueries.delete(key) + } + if (toDelete.length > 0) { + saveSessionMap(this.persistentMap) + } + } }