feat: multiple named conversations for the cooking assistant
The general assistant had exactly one conversation per user forever (recipeId null on chat_messages) — no way to start fresh or organize by topic. Adds an ai_conversations table (title, timestamps) and a nullable conversationId FK on chat_messages; the assistant panel gets a conversations menu to create/switch/rename/delete, auto-titling a new conversation from its first question. Per-recipe chat is untouched — each recipe already has one natural thread, so multi-conversation support only applies to the homepage assistant. Pre-existing general messages (no conversationId) aren't migrated into the new model and won't appear in the conversation list. Requires migration 0042 to run against a live DB — not applied in this sandbox (no Docker here); run `pnpm db:migrate`. v0.43.0
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { db, aiConversations, eq, and } from "@epicure/db";
|
||||
import { requireSessionOrApiKey } from "@/lib/api-auth";
|
||||
|
||||
type Params = { params: Promise<{ id: string }> };
|
||||
|
||||
const RenameSchema = z.object({ title: z.string().max(100).nullable() });
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: Params) {
|
||||
const { session, response } = await requireSessionOrApiKey(req);
|
||||
if (response) return response;
|
||||
const { id } = await params;
|
||||
|
||||
const body = await req.json() as unknown;
|
||||
const parsed = RenameSchema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
return NextResponse.json({ error: "Validation error" }, { status: 400 });
|
||||
}
|
||||
|
||||
const [updated] = await db
|
||||
.update(aiConversations)
|
||||
.set({ title: parsed.data.title?.trim() || null, updatedAt: new Date() })
|
||||
.where(and(eq(aiConversations.id, id), eq(aiConversations.userId, session!.user.id)))
|
||||
.returning();
|
||||
|
||||
if (!updated) return NextResponse.json({ error: "Not found" }, { status: 404 });
|
||||
|
||||
return NextResponse.json({ id: updated.id, title: updated.title });
|
||||
}
|
||||
|
||||
export async function DELETE(req: NextRequest, { params }: Params) {
|
||||
const { session, response } = await requireSessionOrApiKey(req);
|
||||
if (response) return response;
|
||||
const { id } = await params;
|
||||
|
||||
const [deleted] = await db
|
||||
.delete(aiConversations)
|
||||
.where(and(eq(aiConversations.id, id), eq(aiConversations.userId, session!.user.id)))
|
||||
.returning({ id: aiConversations.id });
|
||||
|
||||
if (!deleted) return NextResponse.json({ error: "Not found" }, { status: 404 });
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
Reference in New Issue
Block a user