Skip to content

Commit 86fb19f

Browse files
fix: keep active sidebar session messages cached (#764)
1 parent 9838ef2 commit 86fb19f

2 files changed

Lines changed: 69 additions & 4 deletions

File tree

internal/serveui/static/app-core.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,15 +1172,31 @@ const loadSessions = () => {
11721172
return [];
11731173
};
11741174

1175-
// Evict messages from in-memory sessions beyond the 10 most-recently-created
1176-
// to cap RAM usage. Evicted sessions become lazy-load stubs.
1175+
// Evict messages from in-memory sessions beyond the 10 most-recently-used
1176+
// message-bearing sessions to cap RAM usage. Always keep the active session's
1177+
// messages so a lazy-loaded older sidebar entry does not go blank immediately
1178+
// after switchToSession() saves state.
11771179
const MAX_CACHED_MESSAGE_SESSIONS = 10;
11781180

11791181
const evictStaleSessionMessages = () => {
11801182
const withMessages = state.sessions.filter(s => s.messages && s.messages.length > 0 && !s._serverOnly);
11811183
if (withMessages.length <= MAX_CACHED_MESSAGE_SESSIONS) return;
1182-
withMessages.sort((a, b) => b.created - a.created);
1183-
const keep = new Set(withMessages.slice(0, MAX_CACHED_MESSAGE_SESSIONS).map(s => s.id));
1184+
1185+
const keep = new Set();
1186+
const activeSessionId = String(state.activeSessionId || '').trim();
1187+
if (activeSessionId && withMessages.some(s => s.id === activeSessionId)) {
1188+
keep.add(activeSessionId);
1189+
}
1190+
1191+
withMessages.sort((a, b) => {
1192+
const bAt = Number(b.lastMessageAt || b.created || 0);
1193+
const aAt = Number(a.lastMessageAt || a.created || 0);
1194+
return bAt - aAt;
1195+
});
1196+
for (const session of withMessages) {
1197+
if (keep.size >= MAX_CACHED_MESSAGE_SESSIONS) break;
1198+
keep.add(session.id);
1199+
}
11841200

11851201
for (const s of state.sessions) {
11861202
if (!keep.has(s.id) && s.messages && s.messages.length > 0) {

internal/serveui/static/app_core_test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,55 @@ const app = loadAppCore();
673673
pass(name);
674674
})();
675675

676+
(function testMessageEvictionKeepsActiveOlderSession() {
677+
const name = 'message eviction keeps active older session loaded';
678+
const testApp = loadAppCore();
679+
testApp.state.sessions = Array.from({ length: 11 }, (_, index) => ({
680+
id: `s${index + 1}`,
681+
title: `Session ${index + 1}`,
682+
created: 1000 + index,
683+
lastMessageAt: 1000 + index,
684+
messages: [{ id: `m${index + 1}`, role: 'user', content: 'hi', created: 1000 + index }],
685+
}));
686+
testApp.state.activeSessionId = 's1';
687+
688+
testApp.saveSessions();
689+
690+
const active = testApp.state.sessions.find((session) => session.id === 's1');
691+
if (!active || active._serverOnly || active.messages.length !== 1) {
692+
fail(name, 'active older session was evicted and would render blank');
693+
return;
694+
}
695+
const loaded = testApp.state.sessions.filter((session) => session.messages.length > 0 && !session._serverOnly);
696+
if (loaded.length !== 10) {
697+
fail(name, `expected exactly 10 loaded sessions, got ${loaded.length}`);
698+
return;
699+
}
700+
pass(name);
701+
})();
702+
703+
(function testMessageEvictionUsesRecentActivity() {
704+
const name = 'message eviction prefers recent activity over creation time';
705+
const testApp = loadAppCore();
706+
testApp.state.sessions = Array.from({ length: 11 }, (_, index) => ({
707+
id: `s${index + 1}`,
708+
title: `Session ${index + 1}`,
709+
created: 1000 + index,
710+
lastMessageAt: 1000 + index,
711+
messages: [{ id: `m${index + 1}`, role: 'user', content: 'hi', created: 1000 + index }],
712+
}));
713+
testApp.state.sessions[0].lastMessageAt = 10_000;
714+
715+
testApp.saveSessions();
716+
717+
const recentlyActive = testApp.state.sessions[0];
718+
if (recentlyActive._serverOnly || recentlyActive.messages.length !== 1) {
719+
fail(name, 'recently active older-created session was evicted');
720+
return;
721+
}
722+
pass(name);
723+
})();
724+
676725
if (failures > 0) {
677726
process.exit(1);
678727
}

0 commit comments

Comments
 (0)