feat(dashboard): tableau de bord Second Brain configurable avec chargement progressif
Briefing granulaire, pistes rapides puis enrichissement async, layout persisté v5, suggestions agents, intégration Gmail et navigation sidebar alignée sur /home. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,6 +10,12 @@ import {
|
||||
prepareNoteTextForEmbedding,
|
||||
} from '@/lib/text/plain-text'
|
||||
import { detectTextDirection } from '@/lib/clip/rtl-content'
|
||||
import { detectUserLanguage } from '@/lib/i18n/detect-user-language'
|
||||
import type { SupportedLanguage } from '@/lib/i18n/load-translations'
|
||||
import {
|
||||
buildMemoryEchoInsightPrompt,
|
||||
getMemoryEchoInsightFallback,
|
||||
} from '@/lib/ai/memory-echo-i18n'
|
||||
import {
|
||||
SEMANTIC_SIMILARITY_FLOOR_CLIP,
|
||||
SEMANTIC_SIMILARITY_FLOOR_DEMO,
|
||||
@@ -334,38 +340,16 @@ export class MemoryEchoService {
|
||||
note1Title: string | null,
|
||||
note1Content: string,
|
||||
note2Title: string | null,
|
||||
note2Content: string
|
||||
note2Content: string,
|
||||
language: SupportedLanguage = 'en',
|
||||
): Promise<string> {
|
||||
try {
|
||||
const config = await getSystemConfig()
|
||||
const provider = getChatProvider(config)
|
||||
|
||||
const note1Desc = note1Title || 'Untitled note'
|
||||
const note2Desc = note2Title || 'Untitled note'
|
||||
const excerpt1 = excerptPlainNoteContent(note1Title, note1Content, 1200)
|
||||
const excerpt2 = excerptPlainNoteContent(note2Title, note2Content, 1200)
|
||||
const directionSample = `${note1Desc}\n${excerpt1}\n${note2Desc}\n${excerpt2}`
|
||||
const isRtl = detectTextDirection(directionSample) === 'rtl'
|
||||
|
||||
const prompt = isRtl
|
||||
? `تو یک دستیار هستی که ارتباط بین یادداشتها را تحلیل میکنی.
|
||||
|
||||
یادداشت ۱: «${note1Desc}»
|
||||
متن: ${excerpt1}
|
||||
|
||||
یادداشت ۲: «${note2Desc}»
|
||||
متن: ${excerpt2}
|
||||
|
||||
در یک جمله کوتاه (حداکثر ۱۵ کلمه) به فارسی توضیح بده چرا این دو یادداشت به هم مرتبطاند. فقط رابطه معنایی را بگو.`
|
||||
: `You are a helpful assistant analyzing connections between notes.
|
||||
|
||||
Note 1: "${note1Desc}"
|
||||
Content: ${excerpt1}
|
||||
|
||||
Note 2: "${note2Desc}"
|
||||
Content: ${excerpt2}
|
||||
|
||||
Explain in one brief sentence (max 15 words) why these notes are connected. Focus on the semantic relationship.`
|
||||
const prompt = buildMemoryEchoInsightPrompt(language, note1Title, excerpt1, note2Title, excerpt2)
|
||||
|
||||
const response = await provider.generateText(prompt)
|
||||
|
||||
@@ -375,20 +359,15 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
|
||||
.trim()
|
||||
.substring(0, 150)
|
||||
|
||||
const fallback = isRtl
|
||||
? 'این یادداشتها از نظر معنایی به هم مرتبط به نظر میرسند.'
|
||||
: 'These notes appear to be semantically related.'
|
||||
|
||||
return insight || fallback
|
||||
return insight || getMemoryEchoInsightFallback(language)
|
||||
|
||||
} catch (error) {
|
||||
console.error('[MemoryEcho] Failed to generate insight:', error)
|
||||
const sample = excerptPlainNoteContent(note1Title, note1Content, 200)
|
||||
+ excerptPlainNoteContent(note2Title, note2Content, 200)
|
||||
if (detectTextDirection(sample) === 'rtl') {
|
||||
return 'این یادداشتها از نظر معنایی به هم مرتبط به نظر میرسند.'
|
||||
}
|
||||
return 'These notes appear to be semantically related.'
|
||||
const rtl = detectTextDirection(sample) === 'rtl'
|
||||
if (rtl) return getMemoryEchoInsightFallback(language === 'fa' || language === 'ar' ? language : 'fa')
|
||||
return getMemoryEchoInsightFallback(language)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,12 +463,14 @@ Explain in one brief sentence (max 15 words) why these notes are connected. Focu
|
||||
return null // All connections already shown
|
||||
}
|
||||
|
||||
// Generate AI insight
|
||||
// Generate AI insight in user's language
|
||||
const userLanguage = await detectUserLanguage()
|
||||
const insightText = await this.generateInsight(
|
||||
newConnection.note1.title,
|
||||
newConnection.note1.content,
|
||||
newConnection.note2.title,
|
||||
newConnection.note2.content || ''
|
||||
newConnection.note2.content || '',
|
||||
userLanguage,
|
||||
)
|
||||
|
||||
// Store insight in database
|
||||
|
||||
Reference in New Issue
Block a user