feat: AI Overview recherche + AI Writer inline streaming
- AI Overview : synthèse IA en haut des résultats de recherche (Ctrl+K) - Service search-overview.service.ts - Endpoint /api/ai/search-overview - Carte 'Réponse IA' avec Sparkles en haut du panneau gauche - Pur additif, ne modifie pas le classement des résultats - AI Writer inline : slash menu → 'Écrire avec l'IA' → champ inline - Mode 'write' dans paragraph-refactor.service.ts - Streaming paragraphe par paragraphe (120ms delay) - Nettoyage HTML (espaces vides supprimés) - Ref synchrone pour éviter fermeture du menu pendant la frappe - Fix: index slashCommands AI Writer corrigé - Fix: Loader2 import manquant - i18n FR/EN
This commit is contained in:
@@ -2,12 +2,14 @@
|
||||
|
||||
import { Menu } from 'lucide-react'
|
||||
import { SettingsNav } from '@/components/settings'
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
|
||||
export default function SettingsLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const { t } = useLanguage()
|
||||
return (
|
||||
<div className="flex flex-col h-full bg-[#F2F0E9] dark:bg-dark-paper">
|
||||
<header className="px-4 sm:px-8 md:px-12 pt-8 sm:pt-14 md:pt-20 pb-6 sm:pb-10 md:pb-16 space-y-6 sm:space-y-10 md:space-y-12 shrink-0">
|
||||
@@ -15,16 +17,16 @@ export default function SettingsLayout({
|
||||
<button
|
||||
className="md:hidden p-2 -ms-1 text-ink/70 hover:bg-ink/5 rounded-lg transition-colors shrink-0 mt-1"
|
||||
onClick={() => window.dispatchEvent(new CustomEvent('open-mobile-sidebar'))}
|
||||
aria-label="Ouvrir la navigation"
|
||||
aria-label={t('settings.title')}
|
||||
>
|
||||
<Menu size={22} />
|
||||
</button>
|
||||
<div>
|
||||
<h1 className="text-3xl sm:text-5xl md:text-[64px] font-serif text-ink tracking-tight leading-none italic font-medium">
|
||||
Paramètres
|
||||
{t('settings.title')}
|
||||
</h1>
|
||||
<p className="text-[10px] font-bold uppercase tracking-[0.4em] text-concrete opacity-60 mt-4">
|
||||
Configuration & Préférences
|
||||
{t('settings.description')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
24
memento-note/app/api/ai/search-overview/route.ts
Normal file
24
memento-note/app/api/ai/search-overview/route.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { auth } from '@/auth'
|
||||
import { searchOverviewService } from '@/lib/ai/services/search-overview.service'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
const { query, results, language } = await request.json()
|
||||
if (!query?.trim() || !Array.isArray(results)) {
|
||||
return NextResponse.json({ error: 'query and results required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const overview = await searchOverviewService.generate(query, results, language)
|
||||
|
||||
return NextResponse.json(overview)
|
||||
} catch (error: any) {
|
||||
console.error('[Search Overview] Error:', error)
|
||||
return NextResponse.json({ error: error.message, hasRelevantInfo: false, answer: '' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user