feat: brainstorm sessions, PDF document Q&A, embedding fixes, and UI improvements
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 7s

- Add brainstorm feature with collaborative canvas, AI idea generation, live cursors, playback, and export
- Add PDF upload/extraction/ingestion pipeline with pgvector document search (RAG)
- Add document Q&A overlay with streaming chat and PDF preview
- Add note attachments UI with status polling, grid layout, and auto-scroll
- Add task extraction AI tool and agent executor improvements
- Fix NoteEmbedding missing updatedAt column, re-index 66 notes with 1536-dim embeddings
- Fix brainstorm 'Create Note' button: add success toast and redirect to created note
- Fix memory echo notification infinite polling
- Fix chat route to always include document_search tool
- Add brainstorm i18n keys across all 14 locales
- Add socket server for real-time brainstorm collaboration
- Add hierarchical notebook selector and organize notebook dialog improvements
- Add sidebar brainstorm section with session management
- Update prisma schema with brainstorm tables, attachments, and document chunks
This commit is contained in:
Antigravity
2026-05-14 17:43:21 +00:00
parent 195e845f0a
commit 1fcea6ed7d
228 changed files with 57656 additions and 1059 deletions

View File

@@ -0,0 +1,74 @@
import { format, type Locale } from 'date-fns'
import { toJalaali } from 'jalaali-js'
const JALALI_MONTHS_FA = [
'فروردین',
'اردیبهشت',
'خرداد',
'تیر',
'مرداد',
'شهریور',
'مهر',
'آبان',
'آذر',
'دی',
'بهمن',
'اسفند',
] as const
const PERSIAN_DIGITS = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'] as const
/** Western digits → Persian (Extended Arabic-Indic) numerals, e.g. 1405 → ۱۴۰۵ */
export function toPersianDigits(input: string): string {
return input.replace(/\d/g, (ch) => PERSIAN_DIGITS[Number(ch)] ?? ch)
}
function pad2(n: number): string {
return n < 10 ? `0${n}` : `${n}`
}
function formatJalaliAbsolute(date: Date, pattern: string): string {
const { jy, jm, jd } = toJalaali(date)
const monthName = JALALI_MONTHS_FA[jm - 1]
const h = pad2(date.getHours())
const min = pad2(date.getMinutes())
let s: string
switch (pattern) {
case 'd MMM yyyy':
s = `${jd} ${monthName} ${jy}`
break
case 'd MMM yyyy · HH:mm':
s = `${jd} ${monthName} ${jy} · ${h}:${min}`
break
case 'd MMM yyyy HH:mm':
s = `${jd} ${monthName} ${jy} ${h}:${min}`
break
case 'd MMM · HH:mm':
s = `${jd} ${monthName} · ${h}:${min}`
break
case 'MMM d, yyyy':
s = `${monthName} ${jd}، ${jy}`
break
default:
s = `${jd} ${monthName} ${jy}`
}
return toPersianDigits(s)
}
/**
* Absolute calendar dates for Persian (`fa`) use the Solar Hijri (Jalali / هجری شمسی) calendar.
* Times remain in the user's local timezone. For relative phrases, keep using `formatDistanceToNow` with `faIR`.
*/
export function formatAbsoluteDateLocalized(
date: Date | string,
language: string,
pattern: string,
locale: Locale
): string {
const d = typeof date === 'string' ? new Date(date) : date
if (language === 'fa') {
return formatJalaliAbsolute(d, pattern)
}
return format(d, pattern, { locale })
}