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:
Arnaud
2026-07-17 17:18:49 +02:00
parent 25e624f618
commit c5a8f94b26
17 changed files with 5671 additions and 18 deletions
+18
View File
@@ -461,6 +461,24 @@
"inputPlaceholder": "Ask a question…",
"send": "Send message"
},
"conversations": {
"menuAriaLabel": "Conversations",
"newConversation": "New conversation",
"loading": "Loading…",
"empty": "No conversations yet.",
"untitled": "Untitled",
"renameSave": "Save",
"renameCancel": "Cancel",
"renameAriaLabel": "Rename",
"deleteAriaLabel": "Delete",
"deleteConfirmTitle": "Delete this conversation?",
"deleteConfirmDescription": "This deletes the conversation and all its messages. This can't be undone.",
"deleteCancel": "Cancel",
"deleteConfirm": "Delete",
"createFailed": "Failed to start a new conversation",
"renameFailed": "Failed to rename conversation",
"deleteFailed": "Failed to delete conversation"
},
"servingScaler": {
"servings": "Servings",
"reset": "Reset",
+18
View File
@@ -461,6 +461,24 @@
"inputPlaceholder": "Posez une question…",
"send": "Envoyer le message"
},
"conversations": {
"menuAriaLabel": "Conversations",
"newConversation": "Nouvelle conversation",
"loading": "Chargement…",
"empty": "Aucune conversation pour le moment.",
"untitled": "Sans titre",
"renameSave": "Enregistrer",
"renameCancel": "Annuler",
"renameAriaLabel": "Renommer",
"deleteAriaLabel": "Supprimer",
"deleteConfirmTitle": "Supprimer cette conversation ?",
"deleteConfirmDescription": "Ceci supprime la conversation et tous ses messages. Cette action est irréversible.",
"deleteCancel": "Annuler",
"deleteConfirm": "Supprimer",
"createFailed": "Échec de la création d'une nouvelle conversation",
"renameFailed": "Échec du renommage de la conversation",
"deleteFailed": "Échec de la suppression de la conversation"
},
"servingScaler": {
"servings": "Portions",
"reset": "Réinitialiser",