- Complete rewrite of note-history-modal: version list with inline restore/delete,
split diff view with synced scrolling, rich preview for markdown/richtext/checklist
- Fix restore not updating editor: use key={id-updatedAt} on NoteInlineEditor to
force remount on restore, and add sync useEffect to reset local state on prop changes
- Add sync useEffect in NoteEditor for external note updates
- Add historyEnabled to NOTE_LIST_SELECT (no more 'Activer' on every modal open)
- Replace browser confirm() with shadcn AlertDialog for delete confirmation
- Add i18n keys: currentVersion, compareVersions, diffTitle, diffSelectHint, deleteVersionDesc
- Install diff + @types/diff for visual line diffing
- Fix MasonryGrid render-phase sync to preserve local sizes
- Update notes-tabs-view merge logic for restored note propagation
- Remove debug console.log from restoreNoteVersion
- If /api/ai/convert-markdown fails, abort the type change and show error toast
- Only switch to richtext after successful content conversion
- Switching back to markdown always works (no conversion needed)
- Add i18n keys for conversion success/failure messages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Agent-created notes are now type 'markdown' by default (raw markdown content)
- Switching note type from markdown → richtext auto-converts content to HTML
via /api/ai/convert-markdown endpoint using the existing markdownToHtml utility
- Users can freely switch between markdown and richtext in the note type selector
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add DeepSeek, OpenRouter, Mistral, Z.AI, LM Studio as AI providers
with editable model names via Combobox in admin settings
- Fix OpenRouter broken by normalizeProvider bug in config.ts
- Convert agent-created notes from Markdown to HTML (TipTap rich text)
- Add Notification model + in-app notifications for agent results
- Agent notification click opens the created note directly
- Add note count display on notebook and inbox headers
- Fix checklist toggle in card view (persist state via localCheckItems)
- Add checklist creation option in tabs/list view (dropdown on + button)
- Fix image description ENOENT error with HTTP fallback
- Improve UI contrast across all themes (input, border, checkbox visibility)
- Add font family setting (Inter vs System Default) in Appearance settings
- Fix CSS font-sans variable conflict (removed dead Geist references)
- Update README with new features and 8 providers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Raise MAX_WORDS from 500 to 2000 for text reformulation
- Error messages now use i18n keys (ai.wordCountMin/Max) instead of
hardcoded English strings
- Client translates server errors using the user's UI language
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add reminder action to NoteActions (masonry view) and NoteMetaSidebar (tabs view)
- NotificationPanel now fetches and displays upcoming/overdue reminders alongside share requests
- Badge count includes overdue reminders; overdue items show mark-as-done toggle
- Sidebar trash count refreshes on NoteRefreshContext trigger (no more manual refresh)
- Add "Clear completed" button on reminders page with clearCompletedReminders action
- Add i18n keys for new features (en/fr)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The sync effect in notes-tabs-view was always preferring local.title over
fresh.title from the DB. When a note was created with an AI-generated title,
triggerRefresh() fetched the note with its title from DB, but the merge
overwrote it with the empty local title. Now uses local.title || fresh.title
so fresh titles show through when local is empty.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add image description service + API route for AI-powered image analysis
- Image title generation returns 3 selectable suggestions via TitleSuggestions component
- Add "Describe images" action in AI assistant (individual + collective)
- Fix pin refresh propagation in card and tabs view
- Fix note creation refresh in tabs mode, pass all notes to tabs view
- Add RTL support (dir="auto") on note content elements
- Pass UI language dynamically to AI endpoints instead of hardcoded 'fr'
- Add 18 missing i18n keys in both en.json and fr.json
- Sparkles button on images for AI title generation (bottom-right, pulse animation)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Chat (AIChat floating widget): conversationId was never captured from
the API response, so every message created a new conversation with no
context. Now creates the conversation upfront before streaming (same
pattern as ChatContainer) so the ID persists across messages.
Note history: was stored globally in UserAISettings, so enabling
history on one note enabled it for ALL notes. Now each Note has its
own historyEnabled boolean field. The "Enable history" action only
affects the specific note. A migration adds the column with default
false.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove revalidatePath('/chat') from createConversation — it caused
the server to re-render the /chat page after each new conversation,
which reset the useChat hook state and created a new conversation
for every message instead of continuing the existing one.
Sidebar now refreshes client-side after streaming completes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add noteHistoryMode setting (manual default / auto) with DB migration
- Manual mode: commit button in editor toolbar creates snapshots on demand
- Auto mode: smart snapshots with 20-char diff threshold + 5min cooldown,
structural changes (color, pin, archive, labels) bypass cooldown
- Add delete individual history entries from history modal
- Fix sidebar: Notes nav no longer active on notebook pages
- Fix sidebar icon: replace filled Lightbulb with outlined FileText
- Fix title suggestions: change from amber to sky blue color scheme
- Fix hydration mismatch: add suppressHydrationWarning on locale dates
- Complete i18n: add history, sort, and AI chat translations for all 16 languages
- Translate French AI assistant section (40+ keys) from English to French
- Update README with new features and stack info
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add stop button to all chat interfaces (floating, contextual, full-page)
- Add conversation sliding window (50 messages) to prevent context overflow
- Add chat timeout warning (30s toast)
- Force response language in chat system prompt (mandatory per-locale)
- Add image paste from clipboard in all note editors (card, list, input)
- Fix upload API to infer extension from MIME type for clipboard images
- Add image description support in note AI chat (base64 vision)
- Fix search regex crash on special characters (escape user input)
- Fix search case-insensitivity on PostgreSQL (mode: 'insensitive')
- Add try/catch around semantic search in chat route (prevent blocking)
- Add new chat button to floating AI assistant
- Fix empty thinking bubbles for reasoning models (filter non-text parts)
- Remove duplicate AI assistant toggle from note editor header
- Improve link metadata scraping (timeout, content-type check, relative URLs)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Use prisma.$transaction in auto-label-creation.service with tx client
- Fix DELETE /api/labels to properly JSON.parse + disconnect labelRelations
- Fix PUT /api/labels rename to handle JSON labels
- Graceful error handling in /api/ai/tags and /api/ai/auto-labels
- Client-side label-deleted event in home-client, notes-tabs-view, label-management-dialog
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Empty notebook placeholder: "Carnet vide" → t('notes.emptyNotebook')
- No note selected: "Aucune note sélectionnée" → t('notes.noNoteSelected')
- Descriptions replaced with t('notes.emptyNotebookDesc'), t('notes.selectOrCreateNote')
- Removed French fallback on newNote button title
- Added 4 new i18n keys to all 15 locales
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The floating ai-chat.tsx was not sending the user's language to the
/api/chat endpoint, causing it to always use the English system prompt.
Now passes `language` from useLanguage() hook.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
TS doesn't narrow session.user inside async callback closures.
Extract userId before the dynamic import to satisfy type checking.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add confirmPassword field to registration form with Zod validation
- Replace ~30 hardcoded French/English strings in admin-settings-form
with proper t() i18n calls (Ollama models, Custom models, search test)
- Extract SettingsHeader to client component for i18n support
- Add 15 i18n keys to all 15 locale files (auth + admin.ai + admin.tools)
- Remove debug "Config value" line from embeddings section
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add visibilitychange listener: refreshes agent data immediately when
user returns to the tab (more reliable than interval-only polling)
- Only show toast for actions created within last 5 minutes to avoid
false positives on page reload
- Hide "Prochaine exécution" line entirely if nextRun is in the past
instead of showing confusing "En attente de déclenchement"
- Add detailed logging to cron endpoint for debugging
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add background scheduler in entrypoint: calls /api/cron/agents every
5 minutes to trigger due agents automatically
- Recalculate stale nextRun (past dates) in getAgents() so the display
always shows a future time
- Agent card shows "En attente de déclenchement" instead of "il y a X"
when nextRun is in the past
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add scheduledTime, scheduledDay, timezone fields to Agent schema
- Create calculateNextRun() helper with timezone-aware scheduling
- Add POST /api/cron/agents endpoint for external scheduler
- Calculate nextRun on agent create, update, and after execution
- Add time/day picker in agent form (daily/weekly/monthly)
- Show "Next run" countdown in agent card
- Add i18n keys for schedule UI (FR + EN)
External scheduler (N8N, Vercel Cron) should call /api/cron/agents
every 5-15 min. Requires `prisma db push` to apply schema changes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add trashedAt: null filter to notebook note count queries in /api/notebooks
- Pass isTrashView, onRestore, onPermanentDelete from NoteCard to NoteActions
- Implement handleRestore and handlePermanentDelete in NoteCard
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add triggerRefresh() call after note creation in both masonry (home-client)
and tabs (notes-tabs-view) modes so NotebooksContext reloads notebook counts.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix React bug #33580: remove Suspense boundaries co-located with Link components
- Delete settings/loading.tsx and admin/loading.tsx (root cause of race condition)
- Convert all admin navigation from Next.js Link to anchor tags
- Move admin pages to dedicated (admin) route group
- Add AdminHeader matching main header visual design
- Add AdminSidebar with anchor-based navigation
- Add /api/admin/models route handler (replaces server actions for GET)
- Add /api/debug/client-error for server-side browser error reporting
- Add useNoteRefreshOptional() to fix crash in AdminHeader
- Hide Admin Dashboard menu for non-admin users
- Change app icons from yellow to blue (#3A7CA5) matching brand primary
- Fix admin search bar width to match main header
Made-with: Cursor
MCP server:
- Fix Prisma imports from stale client-generated path to @prisma/client
- Switch schema from SQLite to PostgreSQL for Docker compatibility
- Add prisma generate step to Dockerfile with proper binaryTargets
- Include index-sse.js in Docker build (was excluded by .dockerignore)
- Install openssl and libc6-compat in Alpine image for Prisma runtime
Docker:
- Fix memento-note healthcheck (wget unavailable in bullseye-slim)
Minor fixes:
- scrape.service SSRF protection, middleware route coverage
- canvas-board and note-input type fixes
- next.config turbopack and devIndicators adjustments
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Security:
- Add auth + file type/size validation to upload API
- Add admin auth to /api/admin/ endpoints
- Add SSRF protection to scrape action
- Whitelist fields in PUT /api/notes/[id] to prevent mass assignment
- Protect /lab, /agents, /chat, /canvas, /notebooks routes in middleware
AI provider fixes:
- Add deepseek/openrouter to factory ProviderType (was silently falling back to ollama)
- Fix title-suggestion.service.ts to use factory instead of hardcoded OpenAI
- Fix getAIProvider→getChatProvider in memory-echo, notebook-summary, agent-executor
- Fix getAIProvider→getTagsProvider in notebook-suggestion, title-suggestions, transform-markdown
Functional bugs:
- Fix ALLOW_REGISTRATION AND→OR logic
- Fix note-editor.tsx passing stale props to useAutoTagging instead of local state
- Fix stale Note.embedding type (migrated to NoteEmbedding table)
- Remove hardcoded SQLite path from prisma.ts
Frontend:
- Add AbortController to useAutoTagging and useTitleSuggestions hooks
- Add error rollback to optimistic UI in note-inline-editor
- Remove stale closure over notebookId/language in useAutoTagging
Cleanup:
- Rename docker-compose from keepnotes→memento
- Remove unused unstable_cache import from config.ts
- Remove dead useUndoRedo hook
- Fix TagSuggestion type (add isNewLabel, reasoning)
- Remove dead AIConfig/AIProviderType types
- Fix ghost-tags unused isEmpty var and as any cast
- Fix note-editor titleSuggestions typed as any[]
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove BMAD framework, IDE configs, dev screenshots, test files,
internal docs, and backup files
- Rename keep-notes/ to memento-note/
- Update all references from keep-notes to memento-note
- Add Apache 2.0 license with Commons Clause (non-commercial restriction)
- Add clean .gitignore and .env.docker.example