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>
- Commit untracked 20260428150000_add_note_history migration (creates
NoteHistory table + noteHistory column) that was causing 500s in prod
- Exclude static files (.json, .svg, .ico, etc.) from auth middleware
to fix manifest.json 403
- Add console.error to echo API routes for production debug visibility
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>
This introduces guarded migrations with automatic backups, fixes note creation after DB reset, and wires snapshot/restore history across notes surfaces.
Next.js bakes public/ at build time — dynamically uploaded files were
never served in Docker standalone mode. Store uploads in data/uploads/
and serve via /api/uploads/ with a rewrite for backward compatibility.
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>
Same pattern as TitleSuggestionService: getModel() + generateText
with system/user prompts. LanguageDetectionService (tinyld) auto-detects
note content language. Labels now match note language (Persian note → Persian labels).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use LanguageDetectionService (tinyld) to detect the language of note
content, same pattern as TitleSuggestionService. No more hardcoded
per-language prompts — single prompt with detected language injected.
Labels now match the note content language (e.g. Persian note → Persian labels).
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>
Rewrote prompts to be strict about content relevance — only suggest
labels directly related to THIS note's content. Raised confidence
threshold to 0.5 in code, 0.7 in prompt. Limited to max 2 suggestions
from existing labels. Prevents same labels being suggested for every note.
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>
Log key points in /api/ai/tags and ContextualAutoTagService to trace
where label suggestions fail: notebook lookup, AI raw response,
JSON parsing, filtered results.
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>
- 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 ADD CONSTRAINT for Note.notebookId was not wrapped in an exception
handler, causing P3009 on production when the constraint already existed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Production DB was missing autoLabeling and languageDetection on UserAISettings,
causing 500 errors on echo/connections endpoints. Also adds missing indexes
and fixes Note.notebookId FK to use ON DELETE SET NULL.
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>
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>
Copy all models used by MCP tools with every field, relation, and
index from memento-note/prisma/schema.prisma. No more guessing
which relations are needed — it's an exact subset.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The pipeline only built memento-note, causing mcp-server to run with
stale code/schema after pushes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Remove `embedding` column from MCP Note model (dropped by migration 20260425120000)
- Add missing columns: trashedAt, dismissedFromRecent, contentUpdatedAt, cardSizeMode
- Add NoteEmbedding model and Label.notebook relation
- Use AsyncLocalStorage to pass authenticated userId from API key to tool handlers
- Enable SSE mode and auth in docker-compose for N8N integration
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>
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>
- Replace wget with node http.request in entrypoint (guaranteed
available, better error handling)
- Add 30s polling in agents page to detect new agent executions
- Show toast notification when an agent finishes (success or failure)
- Add logging in scheduler for visibility in docker logs
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>
The en-US Intl format is MM/DD/YYYY but the regex parsing was assigning
capture group 1 (month) to day and capture group 2 (day) to month.
For day 26+ this created an invalid month value (26), causing
RangeError: Invalid time value when formatting the date.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previous migration (20260426130000) may be recorded as failed in
_prisma_migrations after a db push conflict. This new migration with
a different timestamp will be seen as pending and applied with
idempotent SQL that handles both cases.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use DO blocks with EXCEPTION WHEN duplicate_column to safely handle
columns that may already exist from a previous db push.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Create migration 20260426130000_add_agent_schedule_fields with the 3 new
Agent columns (scheduledTime, scheduledDay, timezone). Reverts entrypoint
back to prisma migrate deploy. Removes redundant migration step from
deploy.yaml.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The app uses db push (no migration files), so migrate deploy was a no-op.
Also removes the redundant migration step from deploy.yaml since the
entrypoint now handles schema sync on every container start.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Run database migration after build and before container startup
so schema changes are always applied before the app goes live.
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>