feat(db): extraction des embeddings + mode WAL + config DB provider-agnostic

- Ajout de la table de relation 1-1 NoteEmbedding pour alléger Model Note
- Refactor complet des actions IA sémantique et Memory Echo pour utiliser la jointure
- Migration propre des 85 embeddings locaux existants
- Ajout PRAGMA journal_mode=WAL pour la concurrence au sein de lib/prisma
- Ajout npm run db:switch pour configuration auto SQLite / PostgreSQL
- Fix du compilateur Turbopack et Next-PWA
This commit is contained in:
Sepehr Ramezani
2026-04-17 22:05:19 +02:00
parent a57c277168
commit 3ef5915062
10 changed files with 180 additions and 36 deletions

View File

@@ -61,13 +61,13 @@ export class MemoryEchoService {
where: {
userId,
isArchived: false,
embedding: { not: null } // Only notes with embeddings
noteEmbedding: { isNot: null } // Only notes with embeddings
},
select: {
id: true,
title: true,
content: true,
embedding: true,
noteEmbedding: true,
createdAt: true
},
orderBy: { createdAt: 'desc' }
@@ -81,7 +81,7 @@ export class MemoryEchoService {
const notesWithEmbeddings = notes
.map(note => ({
...note,
embedding: note.embedding ? JSON.parse(note.embedding) as number[] : null
embedding: note.noteEmbedding?.embedding ? JSON.parse(note.noteEmbedding.embedding) as number[] : null
}))
.filter(note => note.embedding && Array.isArray(note.embedding))
@@ -367,7 +367,7 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
id: true,
title: true,
content: true,
embedding: true,
noteEmbedding: true,
createdAt: true,
userId: true
}
@@ -377,7 +377,7 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
return [] // Note not found or doesn't belong to user
}
if (!targetNote.embedding) {
if (!targetNote.noteEmbedding) {
return [] // Note has no embedding
}
@@ -408,15 +408,15 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
const otherNotes = await prisma.note.findMany({
where: {
userId,
id: { not: noteId }, // Exclude the target note
id: { not: noteId },
isArchived: false,
embedding: { not: null }
noteEmbedding: { isNot: null }
},
select: {
id: true,
title: true,
content: true,
embedding: true,
noteEmbedding: true,
createdAt: true
},
orderBy: { createdAt: 'desc' }
@@ -427,7 +427,7 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
}
// Target note embedding (already native Json from PostgreSQL)
const targetEmbedding = targetNote.embedding ? JSON.parse(targetNote.embedding) as number[] : null
const targetEmbedding = targetNote.noteEmbedding?.embedding ? JSON.parse(targetNote.noteEmbedding.embedding) as number[] : null
if (!targetEmbedding) return []
// Check if user has demo mode enabled
@@ -443,9 +443,9 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
// Compare target note with all other notes
for (const otherNote of otherNotes) {
if (!otherNote.embedding) continue
if (!otherNote.noteEmbedding) continue
const otherEmbedding = otherNote.embedding ? JSON.parse(otherNote.embedding) as number[] : null
const otherEmbedding = otherNote.noteEmbedding?.embedding ? JSON.parse(otherNote.noteEmbedding.embedding) as number[] : null
if (!otherEmbedding) continue
// Check if this connection was dismissed