feat: add env setup wizard, fix docker-compose env passthrough and email from field

- 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>
This commit is contained in:
Sepehr Ramezani
2026-04-21 00:29:51 +02:00
parent 19334fdafc
commit d3c2de2000
8 changed files with 1030 additions and 39 deletions

View File

@@ -63,7 +63,7 @@ export async function updateSystemConfig(data: Record<string, string>) {
await prisma.$transaction(operations)
// Invalidate cache after update
revalidateTag('system-config', '/settings')
revalidateTag('system-config')
return { success: true }
} catch (error) {

View File

@@ -486,7 +486,8 @@ export async function createNote(data: {
;(async () => {
try {
// Background task 1: Generate embedding
const provider = getAIProvider(await getSystemConfig())
const bgConfig = await getSystemConfig()
const provider = getAIProvider(bgConfig)
const embedding = await provider.getEmbeddings(content)
if (embedding) {
await prisma.noteEmbedding.upsert({
@@ -505,6 +506,8 @@ export async function createNote(data: {
const autoLabelingEnabled = await getConfigBoolean('AUTO_LABELING_ENABLED', true)
const autoLabelingConfidence = await getConfigNumber('AUTO_LABELING_CONFIDENCE_THRESHOLD', 70)
console.log('[BG] Auto-labeling check: enabled=', autoLabelingEnabled, 'confidence=', autoLabelingConfidence, 'notebookId=', notebookId)
if (autoLabelingEnabled) {
const suggestions = await contextualAutoTagService.suggestLabels(
content,
@@ -512,6 +515,8 @@ export async function createNote(data: {
userId
)
console.log('[BG] Auto-labeling suggestions:', suggestions.length, suggestions.map(s => s.label))
const appliedLabels = suggestions
.filter(s => s.confidence >= autoLabelingConfidence)
.map(s => s.label)
@@ -530,6 +535,8 @@ export async function createNote(data: {
} catch (error) {
console.error('[BG] Auto-labeling failed:', error)
}
} else {
console.log('[BG] Auto-labeling skipped: hasUserLabels=', hasUserLabels, 'notebookId=', notebookId)
}
})()
@@ -556,6 +563,7 @@ export async function updateNote(id: string, data: {
isMarkdown?: boolean
size?: 'small' | 'medium' | 'large'
autoGenerated?: boolean | null
aiProvider?: string | null
notebookId?: string | null
}, options?: { skipContentTimestamp?: boolean; skipRevalidation?: boolean }) {
const session = await auth();