import { Router } from 'express'; import { z } from 'zod'; import * as repo from '../../db/repos/messages.js'; import * as conversations from '../../db/repos/conversations.js'; import { validate } from '../validate.js'; import { NotFoundError, ValidationError, asyncWrap } from '../errors.js'; const appendSchema = z.object({ role: z.string().min(1).max(64), body: z.string().min(1), agent_id: z.string().uuid().nullable().optional(), metadata: z.record(z.string(), z.any()).optional() }); const convParams = z.object({ conversation_id: z.string().uuid() }); export const conversationsScopedRouter = Router({ mergeParams: true }); conversationsScopedRouter.get('/', validate({ params: convParams, query: z.object({ limit: z.string().optional() }) }), asyncWrap(async (req, res) => { const existing = await conversations.getById(req.params.conversation_id); if (!existing) throw new NotFoundError('conversation not found'); const limit = req.validatedQuery.limit ? Number(req.validatedQuery.limit) : 1000; if (!Number.isFinite(limit) || limit < 1 || limit > 5000) { throw new ValidationError('limit must be 1..5000'); } res.json(await repo.listByConversation(req.params.conversation_id, { limit })); }) ); conversationsScopedRouter.post('/', validate({ params: convParams, body: appendSchema }), asyncWrap(async (req, res) => { const existing = await conversations.getById(req.params.conversation_id); if (!existing) throw new NotFoundError('conversation not found'); const row = await repo.append(req.params.conversation_id, req.body); res.status(201).json(row); }) );