From 2235f06ea5bbadb288a1dd9edcff573c752e54d2 Mon Sep 17 00:00:00 2001 From: Aamer Akhter Date: Thu, 18 Jun 2026 12:39:38 -0400 Subject: [PATCH] COD-121 unified session list: live SSE refresh (slice A, unit 4) The complete session list now updates live as sessions change, instead of only on open/welcome-load. - app.js: extra SSE listeners (session:created/updated/deleted) on the same EventSource (multiple listeners per event; existing handlers untouched; registered via addListener so they tear down on reconnect) call _onSessionListMaybeChanged(). - panels-ui.js: _onSessionListMaybeChanged() debounced-refreshes the Session Manager modal when it's open and the welcome list when its overlay is visible (no work when neither is showing). _loadSessionManagerList stores the active query so refreshes preserve the user's search. Verified on an isolated beta instance (Playwright): dispatching a session event refreshes the modal while open, does NOT while closed (gated), and refreshes the welcome list while visible. Gates: tsc 0, frontend-syntax + public-asset format clean, build clean. --- src/web/public/app.js | 9 +++++++++ src/web/public/panels-ui.js | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/web/public/app.js b/src/web/public/app.js index 37e8f411..1c24b0b4 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -1258,6 +1258,15 @@ class CodemanApp { for (const [event] of _SSE_HANDLER_MAP) { addListener(event, this._sseHandlerWrappers.get(event)); } + + // COD-121: live-refresh the unified session list (Session Manager modal + + // visible welcome list) on session structural changes. Extra listeners on the + // same EventSource — EventSource supports multiple listeners per event — so the + // existing handlers above are untouched. Registered through addListener so they + // are torn down with the rest on reconnect. + for (const event of [SSE_EVENTS.SESSION_CREATED, SSE_EVENTS.SESSION_UPDATED, SSE_EVENTS.SESSION_DELETED]) { + addListener(event, () => this._onSessionListMaybeChanged()); + } } // ═══════════════════════════════════════════════════════════════ diff --git a/src/web/public/panels-ui.js b/src/web/public/panels-ui.js index 40353734..6c5ad909 100644 --- a/src/web/public/panels-ui.js +++ b/src/web/public/panels-ui.js @@ -338,7 +338,30 @@ Object.assign(CodemanApp.prototype, { if (modal) modal.classList.remove('active'); }, + /** + * COD-121: live-refresh the unified session list when sessions change + * (created/updated/deleted via SSE). Only touches surfaces that are currently + * showing — the open Session Manager modal and/or the visible welcome list — + * and is debounced so an event burst collapses into one re-fetch. The current + * search query is preserved. + */ + _onSessionListMaybeChanged() { + const modal = document.getElementById('sessionManagerModal'); + if (modal && modal.classList.contains('active')) { + this._debouncedCall( + 'sessionManagerRefresh', + () => this._loadSessionManagerList(this._sessionManagerQuery || ''), + 400 + ); + } + const welcome = document.getElementById('welcomeOverlay'); + if (welcome && welcome.classList.contains('visible')) { + this._debouncedCall('welcomeHistoryRefresh', () => this.loadHistorySessions(), 600); + } + }, + async _loadSessionManagerList(q = '') { + this._sessionManagerQuery = q; const list = document.getElementById('sessionManagerList'); if (!list) return; try {