import type { GatewayRequest, OutboundMessage } from '../protocol.js'; import { makeResponse, makeError, ErrorCode } from '../protocol.js'; import type { SessionManager } from '../../session/manager.js'; import type { SessionBridge } from '../session-bridge.js'; export interface SessionHandlerDeps { sessionManager: SessionManager; sessionBridge?: SessionBridge; } export function createSessionHandlers(deps: SessionHandlerDeps) { return { 'sessions.list': async (request: GatewayRequest): Promise => { const sessionIds = deps.sessionManager.listSessions(); const sessions = sessionIds.map(id => ({ id, messageCount: deps.sessionManager.getSession( id.split(':')[0], id.split(':').slice(1).join(':'), ).getHistory().length, })); return makeResponse(request.id, { sessions }); }, 'sessions.history': async (request: GatewayRequest): Promise => { const params = request.params as { sessionId?: string; limit?: number; offset?: number } | undefined; if (!params?.sessionId) { return makeError(request.id, ErrorCode.InvalidRequest, 'sessionId is required'); } const { sessionId, limit, offset } = params; const parts = sessionId.split(':'); const frontend = parts[0]; const userId = parts.slice(1).join(':'); const session = deps.sessionManager.getSession(frontend, userId); const allMessages = session.getHistory(); const start = offset ?? 0; const end = limit ? start + limit : allMessages.length; const messages = allMessages.slice(start, end); return makeResponse(request.id, { messages, total: allMessages.length, }); }, 'sessions.create': async (request: GatewayRequest): Promise => { const params = request.params as { sessionId?: string } | undefined; const sessionId = params?.sessionId ?? `ws:${Date.now()}`; const parts = sessionId.split(':'); const frontend = parts[0]; const userId = parts.slice(1).join(':'); // Creating a session via getSession is idempotent deps.sessionManager.getSession(frontend, userId); return makeResponse(request.id, { sessionId }); }, 'sessions.delete': async (request: GatewayRequest): Promise => { const params = request.params as { sessionId?: string } | undefined; if (!params?.sessionId) { return makeError(request.id, ErrorCode.InvalidRequest, 'sessionId is required'); } const { sessionId } = params; const parts = sessionId.split(':'); const frontend = parts[0]; const userId = parts.slice(1).join(':'); const session = deps.sessionManager.getSession(frontend, userId); session.clear(); return makeResponse(request.id, { deleted: true, sessionId }); }, 'sessions.switch': async (request: GatewayRequest): Promise => { const params = request.params as { sessionId?: string; connectionId?: string } | undefined; if (!params?.sessionId) { return makeError(request.id, ErrorCode.InvalidRequest, 'sessionId is required'); } if (!deps.sessionBridge) { return makeError(request.id, ErrorCode.InternalError, 'Session switching not available'); } const connectionId = params.connectionId as string; if (!connectionId) { return makeError(request.id, ErrorCode.InvalidRequest, 'connectionId is required'); } try { deps.sessionBridge.switchSession(connectionId, params.sessionId); return makeResponse(request.id, { switched: true, sessionId: params.sessionId }); } catch (err) { const message = err instanceof Error ? err.message : 'Failed to switch session'; return makeError(request.id, ErrorCode.InternalError, message); } }, }; }