- Toolbar: remove text labels from all icon buttons (AI, Save, Preview, Convert)
all buttons now icon-only with title tooltip for accessibility
- Toolbar: reposition PanelRight (info panel toggle) to far right after three-dot menu
- Versioning: decouple getNoteHistory/restoreNoteVersion from global userAISettings.noteHistory
now checks note.historyEnabled directly — unblocks manual per-note history
- Versioning: add 'Sauvegarder cette version' button in Versions tab of info panel
calls commitNoteHistory with visual feedback (spinner → success state)
- note-document-info-panel: import commitNoteHistory, add isSavingVersion state
- notes.ts: fix double guard that silently blocked all history operations
- Les agents créés par run-for-note ont frequency:'one-shot' et sont
filtrés de la page /agents (NOT frequency:'one-shot' dans getAgents)
- Panneau slides : sélecteurs Thème (11 palettes) + Style (sharp/soft/rounded/pill)
- Panneau diagramme : sélecteurs Type (auto/flowchart/mindmap/timeline/
org-chart/architecture/process-map) + Style (sketchy/austere/sketch+)
- Les valeurs sélectionnées sont transmises à l'API et injectées dans le prompt
Co-authored-by: Cursor <cursoragent@cursor.com>
Le bouton Play des cartes agents appelait runAgent (Server Action) qui
attendait executeAgent (~2-5 min) → spinner bloqué sans résultat.
- runAgent retourne immédiatement { success, agentId }
- agent-card.tsx lance un polling toutes les 3s sur GET
/api/agents/run-for-note?agentId= jusqu'au statut terminal
- Toast persistant Sonner pendant la génération, mis à jour au résultat
- Cleanup automatique du polling au démontage
Co-authored-by: Cursor <cursoragent@cursor.com>
- 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
- 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>
- 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>
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>
Backup before migration (pg_dump/SQLite copy), DB connection wait with
retries, idempotent prisma migrate deploy, old backup cleanup (keep 5),
and server refuses to start if migration fails.
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>
syncLabels created Labels with original case (e.g. "Projet") but
searched with .toLowerCase() (e.g. "projet"). On PostgreSQL (case-
sensitive), findMany returned [] → labelRelations disconnected →
orphan cleanup deleted ALL notebook labels.
Fix: use Prisma mode:'insensitive' for findFirst and findMany,
deduplicate case-insensitively while preserving original case.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
After syncing a note's labels, detect and delete labels in the same
notebook that are no longer referenced by any note (neither via JSON
nor labelRelations). Prevents phantom labels from accumulating.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Replace broken upsert (nbScope ?? '') with findFirst+create for null notebookId
- Remove aggressive orphan cleanup that deleted notebook labels after save
- Add syncNoteLabels() to update both Note.labels JSON and labelRelations
- Fix createNote, updateNote, auto-labeling to use syncNoteLabels
- Add fallback: suggestFromExistingLabels → suggestNewLabels if empty
- Lower confidence threshold 0.6→0.3, max suggestions 3→5
- Case-insensitive label matching in suggestions
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The error fallback and non-logged-in fallback in getAISettings were
missing languageDetection and autoLabeling fields, creating a union type
where these could be undefined — breaking the build.
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>
The getAgents() function was recalculating nextRun to future dates when
it found past values. This prevented the cron scheduler from ever
finding due agents (nextRun <= now was always false since getAgents
had already pushed it to the future).
Also fix toast polling: use null sentinel for agents without initial
actions so first execution is still detected. Limit cron to 3 agents
per cycle and add logging.
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>
- 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
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>
- app/api/ai/tags/route.ts: getAIProvider → getTagsProvider (was using
embedding model instead of tags model for legacy tag generation)
- lib/ai/services/auto-label-creation.service.ts: same fix
- hooks/use-auto-tagging.ts: remove notebookId gate that blocked all
suggestions in "General Notes" — the API has a legacy path for this
- app/actions/admin-settings.ts: revalidateTag → updateTag (Next.js 16
requires 2 args for revalidateTag)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Auto-tagging:
- CRITICAL FIX: contextual-auto-tag.service.ts was calling getAIProvider()
(alias for getEmbeddingsProvider) instead of getTagsProvider(). This meant
auto-tagging used the embeddings provider/model instead of the tags one.
Now correctly uses getTagsProvider() in both suggestFromExistingLabels and
suggestNewLabels methods.
- Pass user's detected language to suggestLabels() for localized prompts
(was hardcoded to 'en')
Email:
- Fix Resend "from" field: pass DB config to sendViaResend() instead of
re-fetching from DB. Uses SMTP_FROM from config, with localhost-aware fallback.
- Add "Sender email" field in admin Resend section so users can set SMTP_FROM
- Save SMTP_FROM when Resend is selected (was only saved for SMTP mode)
- Test email button now saves config to DB BEFORE testing, so unsaved form
values are used (was reading stale DB values)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add interactive setup wizard (scripts/setup-env.js) with SQLite/PostgreSQL
choice, AI provider config, email, MCP, admin account creation, and
auto-switch of Prisma schema provider
- Fix docker-compose.yml: remove duplicate environment entries that overrode
env_file values with empty strings (broke AI providers in Docker). Now only
DATABASE_URL, NODE_ENV, NEXT_TELEMETRY_DISABLED remain in environment:
- Fix revalidateTag('system-config', '/settings') crash: Next.js 16 interprets
the second arg as a cacheLife profile, not a path. Caused 500 on all admin
settings saves
- Fix Resend "from" field: was building noreply@localhost which Resend rejects.
Now uses SMTP_FROM from config, with localhost-aware fallback
- Add debug logging for auto-labeling background task
- Default DATABASE_URL changed from user:password to memento:memento
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