initial
This commit is contained in:
45
apps/server/src/routes/ws.ts
Normal file
45
apps/server/src/routes/ws.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import type { Sql } from '../db.js';
|
||||
import type { Broker } from '../services/broker.js';
|
||||
import type { Message } from '../types/api.js';
|
||||
|
||||
export function registerWebSocket(
|
||||
app: FastifyInstance,
|
||||
sql: Sql,
|
||||
broker: Broker
|
||||
): void {
|
||||
app.get<{ Params: { id: string } }>(
|
||||
'/api/ws/sessions/:id',
|
||||
{ websocket: true },
|
||||
async (socket, req) => {
|
||||
const sessionId = req.params.id;
|
||||
|
||||
const session = await sql<{ id: string }[]>`SELECT id FROM sessions WHERE id = ${sessionId}`;
|
||||
if (session.length === 0) {
|
||||
socket.send(JSON.stringify({ type: 'error', error: 'session not found' }));
|
||||
socket.close(1008, 'session not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const messages = await sql<Message[]>`
|
||||
SELECT id, session_id, role, content, tool_calls, tool_results, status, last_seq, created_at
|
||||
FROM messages
|
||||
WHERE session_id = ${sessionId}
|
||||
ORDER BY created_at ASC, id ASC
|
||||
`;
|
||||
socket.send(JSON.stringify({ type: 'snapshot', messages }));
|
||||
|
||||
const unsubscribe = broker.subscribe(sessionId, (frame) => {
|
||||
if (socket.readyState !== socket.OPEN) return;
|
||||
try {
|
||||
socket.send(JSON.stringify(frame));
|
||||
} catch (err) {
|
||||
app.log.warn({ err, sessionId }, 'ws send failed');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('close', () => unsubscribe());
|
||||
socket.on('error', () => unsubscribe());
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user