import { Router } from "express"; import { z } from "zod"; import { answerWithContext, answerWithContextStream } from "../../chat/chatChain.js"; import { addMessage } from "../services/conversationsService.js"; export const chatRouter = Router(); const chatBodySchema = z.object({ message: z.string().min(1), conversationId: z.coerce.number().int().positive().optional(), sessionId: z.string().min(1).optional(), model: z.string().min(1).optional(), options: z .object({ temperature: z.number().min(0).max(2).optional(), top_p: z.number().min(0).max(1).optional() }) .optional() }); chatRouter.post("/", async (req, res, next) => { try { const body = chatBodySchema.parse(req.body); const result = await answerWithContext({ message: body.message, conversationId: body.conversationId, options: body.options }); const userId = req.user?.sub; if (userId && body.conversationId) { try { await Promise.all([ addMessage(body.conversationId, { role: "user", content: body.message }), addMessage(body.conversationId, { role: "assistant", content: result.answer, sources: result.sources }) ]); } catch (err) { console.error("[chat] falha ao salvar mensagem:", err); } } res.json(result); } catch (err) { next(err); } }); chatRouter.post("/stream", async (req, res, next) => { let abortController; try { const body = chatBodySchema.parse(req.body); res.setHeader("Content-Type", "text/event-stream"); res.setHeader("Cache-Control", "no-cache"); res.setHeader("Connection", "keep-alive"); res.setHeader("X-Accel-Buffering", "no"); res.flushHeaders(); abortController = new AbortController(); res.on("close", () => abortController.abort()); const result = await answerWithContextStream({ message: body.message, conversationId: body.conversationId, options: body.options, signal: abortController.signal, onChunk: (delta) => { res.write(`data: ${JSON.stringify({ type: "delta", delta })}\n\n`); } }); res.write(`data: ${JSON.stringify({ type: "sources", sources: result.sources })}\n\n`); res.write("data: [DONE]\n\n"); res.end(); const userId = req.user?.sub; if (userId && body.conversationId) { Promise.all([ addMessage(body.conversationId, { role: "user", content: body.message }), addMessage(body.conversationId, { role: "assistant", content: result.answer, sources: result.sources }) ]).catch((err) => console.error("[chat] falha ao salvar mensagem:", err)); } } catch (err) { if (!res.headersSent) { next(err); } else if (err.name !== "AbortError") { res.write(`data: ${JSON.stringify({ type: "error", error: err.message })}\n\n`); res.end(); } } });