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
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:
175
memento-note/BRAINSTORM-CANVAS-SPEC.md
Normal file
175
memento-note/BRAINSTORM-CANVAS-SPEC.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Brainstorm Canvas — Feature Spec for OpenCode
|
||||
|
||||
## PROJECT CONTEXT
|
||||
- **Stack**: Next.js 15 + Prisma + PostgreSQL (pgvector)
|
||||
- **Location**: ~/dev/Momento/memento-note/
|
||||
- **Existing models**: User, Note, Notebook, Canvas (Excalidraw), Agent, Conversation, Workflow, etc.
|
||||
- **Existing API routes**: /app/api/notes, /notebooks, /ai, /canvas, /chat, /agents, etc.
|
||||
- **UI lib**: Radix UI + Tailwind CSS + shadcn components
|
||||
- **State**: @tanstack/react-query
|
||||
- **Auth**: NextAuth (auth.ts, auth.config.ts)
|
||||
|
||||
## ⚠️ CRITICAL RULES
|
||||
1. **DO NOT modify existing models or API routes** — only ADD new ones
|
||||
2. **DO NOT touch prisma/schema.prisma without creating a migration** — use `npx prisma migrate dev --name add_brainstorm`
|
||||
3. **Study the existing code patterns** before writing new code — match the project conventions
|
||||
4. **Look at how existing API routes are structured** (e.g., /app/api/notes/route.ts) and follow the same pattern
|
||||
5. **Look at how existing components use React Query** and follow the same pattern
|
||||
6. **Use existing UI components** from /components/ui/ (shadcn) — don't install new UI libs
|
||||
7. **The project uses TypeScript** — maintain strict typing
|
||||
8. **Do NOT run npm build** — only dev server if needed for testing
|
||||
|
||||
## FEATURE: Brainstorm Canvas (Wave Brainstorming)
|
||||
|
||||
### Concept
|
||||
A temporary workspace for brainstorming ideas using AI-generated "waves" of ideas, displayed as a radial graph. The output feeds back into the notes system.
|
||||
|
||||
### Data Model — ADD these 2 models to prisma/schema.prisma:
|
||||
|
||||
```prisma
|
||||
model BrainstormSession {
|
||||
id String @id @default(cuid())
|
||||
seedIdea String
|
||||
sourceNoteId String?
|
||||
contextNoteIds String? // JSON array of note IDs
|
||||
exportedNoteId String?
|
||||
userId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
ideas BrainstormIdea[]
|
||||
sourceNote Note? @relation(fields: [sourceNoteId], references: [id])
|
||||
exportedNote Note? @relation(fields: [exportedNoteId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([userId, createdAt])
|
||||
}
|
||||
|
||||
model BrainstormIdea {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
waveNumber Int // 1, 2, or 3
|
||||
title String
|
||||
description String
|
||||
connectionToSeed String?
|
||||
noveltyScore Int?
|
||||
parentIdeaId String? // for "dig deeper" sub-brainstorms
|
||||
convertedToNoteId String?
|
||||
relatedNoteIds String? // JSON array
|
||||
status String @default("active") // active, dismissed, converted
|
||||
positionX Float?
|
||||
positionY Float?
|
||||
createdAt DateTime @default(now())
|
||||
session BrainstormSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
||||
parentIdea BrainstormIdea? @relation("IdeaTree", fields: [parentIdeaId], references: [id])
|
||||
children BrainstormIdea[] @relation("IdeaTree")
|
||||
convertedNote Note? @relation(fields: [convertedToNoteId], references: [id])
|
||||
|
||||
@@index([sessionId])
|
||||
@@index([waveNumber])
|
||||
@@index([status])
|
||||
@@index([parentIdeaId])
|
||||
}
|
||||
```
|
||||
|
||||
Also add relations to User model:
|
||||
```
|
||||
brainstormSessions BrainstormSession[]
|
||||
```
|
||||
|
||||
And to Note model — add these two relations:
|
||||
```
|
||||
sourceBrainstormSessions BrainstormSession[] @relation via sourceNoteId
|
||||
exportedBrainstormSessions BrainstormSession[] @relation via exportedNoteId
|
||||
convertedBrainstormIdeas BrainstormIdea[] @relation via convertedToNoteId
|
||||
```
|
||||
|
||||
### API Routes — Create /app/api/brainstorm/
|
||||
|
||||
1. **POST /api/brainstorm/wave** — Create new brainstorm session
|
||||
- Input: { seedIdea, sourceNoteId?, contextNoteIds? }
|
||||
- Uses existing AI setup (check how /api/ai/ routes call LLM)
|
||||
- Generates 3 waves of ~3 ideas each (9 total)
|
||||
- For each idea, does an embedding search to find related notes (check how semantic search works in existing code)
|
||||
- Saves session + ideas to DB
|
||||
- Returns: { sessionId, ideas: [...] }
|
||||
|
||||
2. **POST /api/brainstorm/[sessionId]/expand** — Dig deeper on an idea
|
||||
- Input: { ideaId }
|
||||
- Uses the clicked idea as new seed
|
||||
- Generates 3 more waves, linked as children
|
||||
- Returns new ideas with parentIdeaId set
|
||||
|
||||
3. **POST /api/brainstorm/[sessionId]/dismiss** — Mark idea as not relevant
|
||||
- Input: { ideaId }
|
||||
- Sets status = "dismissed"
|
||||
|
||||
4. **POST /api/brainstorm/[sessionId]/convert** — Convert idea to a real Note
|
||||
- Input: { ideaId }
|
||||
- Creates a Note with pre-filled content
|
||||
- Auto-tags: "brainstorm", "idée"
|
||||
- Links to source note if exists
|
||||
- Sets idea.status = "converted", idea.convertedToNoteId = newNote.id
|
||||
- Returns the created note
|
||||
|
||||
5. **POST /api/brainstorm/[sessionId]/export** — Export session as summary note
|
||||
- Generates a Markdown summary note
|
||||
- Groups by waves, shows which ideas were converted
|
||||
- Links to all converted notes
|
||||
- Returns the created note
|
||||
|
||||
6. **GET /api/brainstorm** — List user's brainstorm sessions
|
||||
- Returns sessions ordered by date, with idea counts
|
||||
|
||||
7. **GET /api/brainstorm/[sessionId]** — Get full session with ideas
|
||||
- Returns session + all ideas + their status
|
||||
|
||||
### Frontend — Canvas Component
|
||||
|
||||
Use **react-force-graph-2d** (install it: `npm install react-force-graph-2d`).
|
||||
It's a React wrapper around d3-force — declarative API, same physics engine.
|
||||
|
||||
**Layout:**
|
||||
- Center node = seed idea (large, white)
|
||||
- Ring 1 (radius ~150px) = Wave 1 ideas (orange)
|
||||
- Ring 2 (radius ~300px) = Wave 2 ideas (blue)
|
||||
- Ring 3 (radius ~450px) = Wave 3 ideas (purple)
|
||||
- Use d3.forceRadial for ring constraint
|
||||
- Dismissed nodes = opacity 0.3, smaller
|
||||
- Converted nodes = green border + icon
|
||||
- Click node = side panel with details + 3 action buttons
|
||||
|
||||
**Side Panel (when clicking a node):**
|
||||
- Show: title, description, connection to seed, related notes
|
||||
- 3 buttons: Dig Deeper, Create Note, Dismiss
|
||||
- Uses existing shadcn Sheet or Dialog component
|
||||
|
||||
**Sidebar Integration:**
|
||||
- Add "Brainstorms" section in the existing sidebar
|
||||
- List sessions with preview (seed idea + count)
|
||||
- Click to reopen saved canvas state
|
||||
|
||||
**Entry Points:**
|
||||
1. From a note: Brainstorm button in note toolbar/editor
|
||||
2. From sidebar: "+ New Brainstorm" button
|
||||
|
||||
### AI Prompt for Wave Generation
|
||||
|
||||
The LLM prompt should generate 3 waves:
|
||||
- **Wave 1 — Variations**: Direct variations/expansions of the seed (sous-aspects, reformulations, variations)
|
||||
- **Wave 2 — Analogies**: Cross-domain analogies (autres domaines, biologie, technologie, etc.)
|
||||
- **Wave 3 — Disruptions**: Inversions, provocations, ideas that challenge assumptions
|
||||
|
||||
Each idea should have:
|
||||
- title (short)
|
||||
- description (1-2 sentences)
|
||||
- connectionToSeed (how it relates to the seed)
|
||||
- noveltyScore (1-10)
|
||||
|
||||
### Implementation Order
|
||||
1. Prisma schema + migration
|
||||
2. API routes (start with /wave and /convert)
|
||||
3. Brainstorm canvas component (react-force-graph-2d)
|
||||
4. Sidebar integration
|
||||
5. Note toolbar button
|
||||
6. Export functionality
|
||||
Reference in New Issue
Block a user