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.
This commit is contained in:
Aamer Akhter
2026-07-12 12:19:10 -04:00
parent 65b609b6db
commit 2235f06ea5
2 changed files with 32 additions and 0 deletions
+9
View File
@@ -1258,6 +1258,15 @@ class CodemanApp {
for (const [event] of _SSE_HANDLER_MAP) { for (const [event] of _SSE_HANDLER_MAP) {
addListener(event, this._sseHandlerWrappers.get(event)); 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());
}
} }
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
+23
View File
@@ -338,7 +338,30 @@ Object.assign(CodemanApp.prototype, {
if (modal) modal.classList.remove('active'); 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 = '') { async _loadSessionManagerList(q = '') {
this._sessionManagerQuery = q;
const list = document.getElementById('sessionManagerList'); const list = document.getElementById('sessionManagerList');
if (!list) return; if (!list) return;
try { try {