- Sessions route now reads giteaRepo from project.data and forwards it
to /agent/execute so the runner can clone/update the correct repo
- PATCH route now validates x-agent-runner-secret header to prevent
unauthorized session output injection
Made-with: Cursor
- Build page: full file tree (lazy-load dirs) + code preview panel
with line numbers and token-level syntax colouring (VS Code dark theme)
- New API route /api/projects/[id]/file proxies Gitea contents API
returning directory listings or decoded file content
- Sidebar Apps section now links to /build instead of raw Gitea URL
- Status indicator replaced with a proper coloured dot (amber/blue/green)
alongside the status label text
Made-with: Cursor
Add ::text cast to all $1/$2 parameters so PostgreSQL never needs
to infer types. Split SELECT and UPDATE into separate try/catch blocks
with distinct error labels so logs show exactly which query fails.
Made-with: Cursor
PostgreSQL could not determine the type of $2 in 'WHERE id = $2'
when id column type is UUID. Casting the column (id::text = $1)
sidesteps the extended-protocol type inference issue. Also moves
projectId to $1 to match the proven working pattern in other routes.
Made-with: Cursor
The PATCH handler used SQL 'updated_at = NOW()' which doesn't exist
on fs_projects (all timestamps live inside the data JSONB blob).
Rewrote to use the same read-merge-write pattern as other working
routes: fetch current data, merge in JS, write back as data::jsonb.
Made-with: Cursor
- Architecture route now uses /generate endpoint (no Atlas session
overhead, no conflicting system prompt) for clean JSON generation
- Design page fetches saved architecture on load and maps designSurfaces
to known surface IDs via fuzzy match; AI-suggested surfaces are
pre-selected in the picker with an "AI" badge and explanatory note
Made-with: Cursor
- GET /api/projects/[id]/atlas-chat returns stored user+assistant messages
- POST handles __atlas_init__ trigger: runs once when no history exists,
not stored as a user turn so Atlas intro appears cleanly
- Rewrite AtlasChat.tsx: fully self-contained component with own message
state; loads history from DB on mount, only greets on first open
- Remove assistant-ui runtime dependency for message persistence
- Add Vision & Success Metrics, Integrations & Dependencies, Open Questions
to PRD section tracker (now 12 sections matching the PDF)
Made-with: Cursor
Phase 1: user picks which surfaces their product needs (Web App,
Marketing Site, Admin, Mobile, Email, Docs). Phase 2: per-surface
horizontal card gallery with mini visual previews of each UI library.
Lock in confirms the choice; locked themes are saved to DB and shown
to the AI coder. Surfaces and themes stored in fs_projects.data.
Made-with: Cursor
Replaces the old design page with a per-app package selector. Fetches
real apps/ from the project's Gitea repo and lets users assign a UI
library (shadcn, DaisyUI, HeroUI, Mantine, Headless UI, or Tailwind
only) independently per app. Selections saved to fs_projects.data.designPackages.
Made-with: Cursor
entrypoint.sh: removed --accept-data-loss from prisma db push.
That flag was silently dropping fs_users, fs_projects etc. on every
container restart, wiping all user/project data. Made the push
non-fatal so a schema mismatch doesn't block startup.
create/route.ts: fixed same broken ON CONFLICT expression as
authOptions.ts — replaced with explicit SELECT + INSERT/UPDATE
to reliably upsert fs_users before inserting the project.
Made-with: Cursor
agent-chat/route.ts:
- Loads conversation history from chat_conversations before each turn
- Passes history + knowledge context to agent runner
- Saves returned history back to chat_conversations after each turn
- Saves AI-generated memory updates to fs_knowledge_items
knowledge/route.ts (new):
- GET /api/projects/[id]/knowledge — list all knowledge items
- POST /api/projects/[id]/knowledge — add/update item by key
- DELETE /api/projects/[id]/knowledge?id=xxx — remove item
OrchestratorChat.tsx:
- Added "Saved to memory" label for save_memory tool calls
Made-with: Cursor
- Tool call names now show human-readable labels ("Dispatched agent"
instead of "spawn_agent"), deduped if called multiple times
- Model label only shown when a real value is returned; "unknown"
and null are suppressed; model names shortened (GLM-5, Gemini)
Made-with: Cursor
Was importing from @/lib/auth (which doesn't exist); correct path
is @/lib/auth/authOptions — this caused the Turbopack build to fail.
Made-with: Cursor
- POST /api/projects/[id]/workspace: provisions a Cloud Run Theia service
on demand and saves the URL to the project record
- overview/page.tsx: shows 'Provision IDE' button when theiaWorkspaceUrl
is null, 'Open IDE' link once provisioned
- Also fixes log spam: retired Firebase session tracking endpoint (410 Gone)
Co-authored-by: Cursor <cursoragent@cursor.com>
Returns 410 Gone instead of crashing with adminDb.collection errors.
Was flooding logs with TypeError on every call from the old Cursor extension.
Co-authored-by: Cursor <cursoragent@cursor.com>
- gemini-client.ts: replaces Vertex AI REST + service account auth with
direct generativelanguage.googleapis.com calls using GOOGLE_API_KEY.
Removes all Firebase credential setup code.
- summarize/route.ts: same migration, simplified to a single fetch call.
- No longer depends on gen-lang-client-0980079410 GCP project for AI calls.
Co-authored-by: Cursor <cursoragent@cursor.com>
- lib/cloud-run-workspace.ts: provisions per-project Theia workspaces as
Cloud Run services (theia-{slug}), scales to zero when idle, starts in
~5-15s from cached image
- create/route.ts: imports cloud-run-workspace instead of coolify-workspace
- Image: northamerica-northeast1-docker.pkg.dev/master-ai-484822/vibn-ide/theia:latest
- Includes prewarmWorkspace() for near-zero perceived load time on login
Co-authored-by: Cursor <cursoragent@cursor.com>
- lib/coolify-workspace.ts: creates a Coolify docker-image app at
{slug}.ide.vibnai.com for each project, patches in vibn-auth Traefik
labels, sets env vars, and starts deployment
- create/route.ts: provisions Theia workspace after Gitea repo creation;
stores theiaWorkspaceUrl + theiaAppUuid on the project record
- theia-auth/route.ts: for *.ide.vibnai.com hosts, verifies the
authenticated user is the project owner (slug → fs_projects lookup)
- overview/page.tsx: Open IDE always links (dedicated URL or shared fallback)
- project-creation-modal.tsx: shows dedicated workspace URL in success screen
Co-authored-by: Cursor <cursoragent@cursor.com>
Firebase was not configured so every chat request crashed with
'Firebase Admin credentials not configured'.
- chat-mode-resolver.ts: read project phase from fs_projects (Postgres)
- chat-context.ts: load project data from fs_projects instead of Firestore
- /api/ai/conversation: store/retrieve conversations in chat_conversations
Postgres table (created automatically on first use)
- /api/ai/chat: replace all Firestore reads/writes with Postgres queries
- v_ai_chat/page.tsx: replace Firebase client auth with useSession from
next-auth/react; remove Firestore listeners, use REST API for project data
Co-authored-by: Cursor <cursoragent@cursor.com>
Two issues:
1. ForwardAuth redirect used x-forwarded-host which Traefik sets to
vibnai.com (the auth service host), not theia.vibnai.com. Now
hardcodes THEIA_URL as the callbackUrl destination.
2. /auth page ignored callbackUrl and always sent users to
/marks-account/projects. Now follows callbackUrl when it points
to theia.vibnai.com, so users land in the IDE after login.
Co-authored-by: Cursor <cursoragent@cursor.com>
db-postgres.ts query() returns T[] directly, not a QueryResult object.
result.rows was undefined, causing the session lookup to always
return null and redirect to login even with a valid session token.
Co-authored-by: Cursor <cursoragent@cursor.com>
Prisma maps sessionToken → session_token and userId → user_id
in the PostgreSQL sessions table. The forwardAuth query was using
the wrong camelCase column names.
Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid importing authOptions/PrismaClient in the forwardAuth endpoint.
Under --network host (Coolify's build flag), routes that import Prisma
at module evaluation time are silently dropped from the build output.
Instead, read the NextAuth session-token cookie directly and verify
it with a raw SQL query against the sessions table - the same pattern
used by other working API routes via @/lib/db-postgres.
Co-authored-by: Cursor <cursoragent@cursor.com>
next-auth/jwt subpath import causes Next.js to silently drop the
route from the standalone build output. Switch to getServerSession
which is used by all other working API routes.
Co-authored-by: Cursor <cursoragent@cursor.com>
NextAuth catches all /api/auth/* routes via [...nextauth] catch-all.
Move the Traefik forwardAuth endpoint to /api/theia-auth to avoid
the conflict. Traefik dynamic config updated to match.
Co-authored-by: Cursor <cursoragent@cursor.com>
POST /api/auth/theia-check validates the NextAuth session cookie
forwarded by Traefik. Returns 200 for authenticated users with
X-Auth-User/Email/Name headers, or 302 redirect to /auth for
unauthenticated requests — preserving the original Theia URL as
callbackUrl so users land back in the IDE after login.
Co-authored-by: Cursor <cursoragent@cursor.com>
BREAKING CHANGE: Replace SuperTokens with NextAuth.js
Why:
- SuperTokens had persistent Traefik routing issues
- SSL certificate not issuing correctly
- Complex infrastructure (separate container)
- NextAuth runs in Next.js app (simpler, no separate service)
Changes:
- Install next-auth, @auth/prisma-adapter, prisma
- Create NextAuth API route: app/api/auth/[...nextauth]/route.ts
- Add Prisma schema for NextAuth tables (users, sessions, accounts)
- Update auth page to use NextAuth signIn()
- Remove all SuperTokens code and dependencies
- Keep same Google OAuth (just simpler integration)
Benefits:
- No separate auth service needed
- No Traefik routing issues
- Sessions stored in Montreal PostgreSQL
- Simpler configuration
- Battle-tested, widely used
All authentication data stays in Montreal!
Co-authored-by: Cursor <cursoragent@cursor.com>