feat(notes): liens internes, onglet Réseau, living blocks et consentement IA
Some checks failed
CI / Lint, Test & Build (push) Failing after 1m19s
CI / Deploy production (on server) (push) Has been skipped

Rend les liens entre notes visibles et persistants (sync NoteLink au save, auto-save, graphe réseau rafraîchi), ajoute living blocks, Memory Echo, recherche globale, consentement IA explicite et consolide les prototypes design en architectural-grid.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Antigravity
2026-05-24 14:27:29 +00:00
parent 077e665dfc
commit e2672cd2c2
323 changed files with 20670 additions and 42431 deletions

View File

@@ -22,6 +22,7 @@ import { exportExcalidrawSceneToPngBlob } from '@/lib/client/excalidraw-export-i
import { useLanguage } from '@/lib/i18n'
import { MarkdownContent } from '@/components/markdown-content'
import { toast } from 'sonner'
import { useAiConsent } from '@/components/legal/ai-consent-provider'
// ── Custom Toast Helper ──────────────────────────────────────────────────────
const mToast = {
@@ -195,6 +196,7 @@ export function ContextualAIChat({
}: ContextualAIChatProps) {
const { t, language } = useLanguage()
const webSearchAvailable = useWebSearchAvailable()
const { requestAiConsent } = useAiConsent()
const [activeTab, setActiveTab] = useState<'chat' | 'actions' | 'resource'>('actions')
const [selectedTone, setSelectedTone] = useState('professional')
@@ -282,6 +284,11 @@ export function ContextualAIChat({
const handleSend = async () => {
const text = input.trim()
if (!text || isLoading) return
// GDPR AI Consent Check
const consented = await requestAiConsent()
if (!consented) return
setInput('')
try {
await sendMessage({ text }, { body: buildChatBody() })
@@ -293,6 +300,10 @@ export function ContextualAIChat({
// ── Action execution ────────────────────────────────────────────────────────
const handleAction = async (action: ActionDef, targetLang?: string) => {
// GDPR AI Consent Check
const consented = await requestAiConsent()
if (!consented) return
if (action.isImageAction) {
if (!noteImages || noteImages.length === 0) {
mToast.error(t('ai.noImagesError') || 'Aucune image dans cette note')
@@ -511,6 +522,10 @@ export function ContextualAIChat({
return
}
// GDPR AI Consent Check
const consented = await requestAiConsent()
if (!consented) return
setResourceEnriching(true)
try {
const res = await fetch('/api/ai/enrich-from-resource', {
@@ -552,6 +567,10 @@ export function ContextualAIChat({
return
}
// GDPR AI Consent Check
const consented = await requestAiConsent()
if (!consented) return
setResourceEnriching(true)
try {
const res = await fetch('/api/ai/enrich-from-resource', {