feat: persist AI chat history, add search across it

Both chat panels (per-recipe and the general cooking assistant) previously
kept messages in component state only — closing the sheet or reloading
the page lost everything. Both POST routes now persist question+answer
pairs to a new chat_messages table (recipeId null for the general
assistant), and both panels load their own history back on open.

New GET /api/v1/ai/chat-history (scoped by recipeId, or scope=general for
the homepage assistant, or neither to search across everything) backs a
new search control in both panels' header — debounced, shows matched
messages with date and (when searching across everything) which recipe
they belonged to.

Verified locally: asked a real question, closed and reopened the panel
and confirmed the conversation reloaded, then searched a keyword from
that conversation and confirmed both the question and answer surfaced
in the results dropdown.
This commit is contained in:
Arnaud
2026-07-12 22:37:39 +02:00
parent 0062220d8e
commit 96ef5b8379
8 changed files with 237 additions and 9 deletions
+10
View File
@@ -388,6 +388,13 @@
"inputPlaceholder": "Posez une question…",
"send": "Envoyer le message"
},
"chatHistory": {
"searchAriaLabel": "Rechercher dans l'historique",
"searchPlaceholder": "Rechercher une question passée…",
"searching": "Recherche…",
"noResults": "Aucun message correspondant",
"close": "Fermer"
},
"cookingChat": {
"sorry": "Désolé, je n'ai pas pu répondre à cela.",
"error": "Une erreur s'est produite. Veuillez réessayer.",
@@ -1153,6 +1160,9 @@
"lastUsedOn": "Utilisée le {date}",
"neverUsed": "Jamais utilisée",
"revoke": "Révoquer",
"apiKeyScopeFull": "Accès complet",
"apiKeyScopeRead": "Lecture seule",
"apiKeyScopeHelp": "Les clés en lecture seule ne peuvent faire que des requêtes GET — elles ne peuvent rien créer, modifier ou supprimer.",
"copyFailed": "Échec de la copie dans le presse-papiers",
"byokSaved": "Clé {provider} enregistrée",
"byokSaveFailed": "Échec de l'enregistrement de la clé",