feat(gateway): expand sessions surface with operator metadata and paging hardening

This commit is contained in:
William Valentin
2026-02-17 16:14:06 -08:00
parent 47187aa878
commit 9c9ab92e9d
7 changed files with 309 additions and 25 deletions
+13
View File
@@ -59,6 +59,19 @@ describe('SessionManager', () => {
expect(sessions).toContain('tui:local');
});
it('can include persisted sessions and frontend filters', () => {
const persisted = manager.getSession('telegram', 'persisted-user');
persisted.addMessage({ role: 'user', content: 'persist me' });
// Simulate daemon restart with empty in-memory map.
manager.evictSessions(['telegram:persisted-user']);
manager.getSession('ws', 'active-user');
expect(manager.listSessions()).toEqual(['ws:active-user']);
expect(manager.listSessions({ includePersisted: true })).toEqual(['telegram:persisted-user', 'ws:active-user']);
expect(manager.listSessions({ includePersisted: true, frontend: 'telegram' })).toEqual(['telegram:persisted-user']);
});
it('indexes and searches history when enabled', () => {
manager = new SessionManager(store, {
enabled: true,
+16 -2
View File
@@ -154,8 +154,22 @@ export class SessionManager {
auditLogger?.sessionTransfer(fromSession.id, toSession.id, history.length);
}
listSessions(): string[] {
return Array.from(this.sessions.keys());
listSessions(opts?: { includePersisted?: boolean; frontend?: string }): string[] {
const ids = new Set<string>(this.sessions.keys());
if (opts?.includePersisted) {
for (const id of this.store.listSessions()) {
ids.add(id);
}
}
let sessions = Array.from(ids.values());
if (opts?.frontend) {
const prefix = `${opts.frontend}:`;
sessions = sessions.filter((id) => id.startsWith(prefix));
}
sessions.sort((a, b) => a.localeCompare(b));
return sessions;
}
closeSession(frontend: string, userId: string): void {