Auto-create chat tables on first request (IF NOT EXISTS)
fs_chat_threads and fs_chat_messages were referenced in code but never added to the migration script. Added ensureChatTables() called at startup of both /api/chat and /api/chat/threads routes — safe, idempotent, and runs once per process lifetime. Also backfilled the SQL migration file for documentation. Made-with: Cursor
This commit is contained in:
@@ -21,6 +21,34 @@ import type { ChatMessage, ToolCall } from '@/lib/ai/gemini-chat';
|
||||
|
||||
const MAX_TOOL_ROUNDS = 6;
|
||||
|
||||
let chatTablesReady = false;
|
||||
async function ensureChatTables() {
|
||||
if (chatTablesReady) return;
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS fs_chat_threads (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
||||
user_id TEXT NOT NULL,
|
||||
workspace TEXT NOT NULL DEFAULT '',
|
||||
data JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS fs_chat_threads_user_ws_idx
|
||||
ON fs_chat_threads (user_id, workspace, updated_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fs_chat_messages (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
thread_id TEXT NOT NULL REFERENCES fs_chat_threads(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL,
|
||||
data JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS fs_chat_messages_thread_idx
|
||||
ON fs_chat_messages (thread_id, created_at ASC);
|
||||
`, []);
|
||||
chatTablesReady = true;
|
||||
}
|
||||
|
||||
function buildSystemPrompt(projects: any[], workspace: string): string {
|
||||
const projectsText = projects.length
|
||||
? projects
|
||||
@@ -55,6 +83,8 @@ You can take real actions by calling tools:
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
await ensureChatTables();
|
||||
|
||||
const session = await authSession();
|
||||
if (!session?.user?.email) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
|
||||
@@ -6,7 +6,36 @@ import { NextResponse } from 'next/server';
|
||||
import { authSession } from '@/lib/auth/session-server';
|
||||
import { query } from '@/lib/db-postgres';
|
||||
|
||||
let chatTablesReady = false;
|
||||
async function ensureChatTables() {
|
||||
if (chatTablesReady) return;
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS fs_chat_threads (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
||||
user_id TEXT NOT NULL,
|
||||
workspace TEXT NOT NULL DEFAULT '',
|
||||
data JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS fs_chat_threads_user_ws_idx
|
||||
ON fs_chat_threads (user_id, workspace, updated_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fs_chat_messages (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
thread_id TEXT NOT NULL REFERENCES fs_chat_threads(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL,
|
||||
data JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS fs_chat_messages_thread_idx
|
||||
ON fs_chat_messages (thread_id, created_at ASC);
|
||||
`, []);
|
||||
chatTablesReady = true;
|
||||
}
|
||||
|
||||
export async function GET(request: Request) {
|
||||
await ensureChatTables();
|
||||
const session = await authSession();
|
||||
if (!session?.user?.email) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
|
||||
@@ -33,6 +62,7 @@ export async function GET(request: Request) {
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
await ensureChatTables();
|
||||
const session = await authSession();
|
||||
if (!session?.user?.email) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
|
||||
|
||||
@@ -155,5 +155,34 @@ CREATE TABLE IF NOT EXISTS verification_tokens (
|
||||
UNIQUE (identifier, token)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- fs_chat_threads (Vibn AI chat conversation threads)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS fs_chat_threads (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
||||
user_id TEXT NOT NULL,
|
||||
workspace TEXT NOT NULL DEFAULT '',
|
||||
data JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS fs_chat_threads_user_ws_idx
|
||||
ON fs_chat_threads (user_id, workspace, updated_at DESC);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- fs_chat_messages (individual messages within a thread)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS fs_chat_messages (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
thread_id TEXT NOT NULL REFERENCES fs_chat_threads(id) ON DELETE CASCADE,
|
||||
user_id TEXT NOT NULL,
|
||||
data JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS fs_chat_messages_thread_idx
|
||||
ON fs_chat_messages (thread_id, created_at ASC);
|
||||
|
||||
-- Done
|
||||
SELECT 'Migration complete' AS status;
|
||||
|
||||
Reference in New Issue
Block a user