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>
- 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
Docker:
- Restrict PostgreSQL port to 127.0.0.1 only (not exposed to LAN)
- Add APP_BASE_URL for MCP server to reach Next.js via Docker network
- Fix MCP healthcheck (remove always-passing fallback)
- Add resource limits to mcp-server container
Dockerfile:
- Remove full node_modules copy (standalone already includes deps)
Reduces image size by ~500MB+
Config:
- Add MCP_SERVER_MODE and MCP_SERVER_URL to deploy.sh and .env.docker.example
- Deploy script now auto-sets MCP_SERVER_URL based on NEXTAUTH_URL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Covers: server setup, Gitea Runner installation (systemd + Docker),
SSH key configuration, CI/CD workflow explanation, Nginx reverse
proxy config with SSE support, HTTPS with Let's Encrypt, admin
user creation, and a full deployment checklist.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- 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>
Reverted all changes to lib/mail.ts and the email section of
admin-settings-form.tsx. The original Resend code was working fine;
my "fixes" for the from field broke it. Restored the exact original
code that was functional.
Kept: auto-tagging fix (getTagsProvider), language detection, revalidateTag
fix, debug logging, docker-compose fix, setup wizard.
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>