batch3 T3: broker user channel + /api/ws/user + project/session/inference emits

- broker.subscribeUser/publishUser via separate user topics map
- /api/ws/user WS route subscribes to the user channel
- projects/sessions POST/DELETE handlers emit lifecycle frames
- inference 3 terminal-state sites emit session_updated with RETURNING

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 15:06:31 +00:00
parent d88b3348a2
commit 8fc525eab9
7 changed files with 132 additions and 50 deletions

View File

@@ -4,6 +4,7 @@ import { realpath, stat, readdir, access } from 'node:fs/promises';
import { basename, resolve, sep } from 'node:path';
import type { Sql } from '../db.js';
import type { Config } from '../config.js';
import type { Broker } from '../services/broker.js';
import type { Project, AvailableProject } from '../types/api.js';
const AddProjectBody = z.object({
@@ -42,7 +43,8 @@ async function resolveProjectPath(
export function registerProjectRoutes(
app: FastifyInstance,
sql: Sql,
config: Config
config: Config,
broker: Broker
): void {
app.get('/api/projects', async () => {
const rows = await sql<Project[]>`
@@ -71,6 +73,7 @@ export function registerProjectRoutes(
VALUES (${name}, ${resolved.real})
RETURNING id, name, path, added_at, last_session_id
`;
broker.publishUser(req.user!, { type: 'project_created', project: row as unknown as Project });
reply.code(201);
return row;
} catch (err) {
@@ -89,6 +92,7 @@ export function registerProjectRoutes(
reply.code(404);
return { error: 'not found' };
}
broker.publishUser(req.user!, { type: 'project_deleted', project_id: id });
reply.code(204);
return null;
});