import { NextRequest } from "next/server"; import { createAuthenticatedClient } from "@/lib/serverSupabase"; import { loadBuiltInKnowledge } from "@/lib/rag"; export const runtime = "nodejs"; function builtIns() { return loadBuiltInKnowledge().map((document, index) => ({ id: `builtin-${index}`, name: `${document.source}.md`, slug: document.source, sizeBytes: Buffer.byteLength(document.content), words: document.content.split(/\s+/).length, preview: document.content.slice(0, 180).replace(/\n/g, " "), modifiedAt: null, projectId: null, builtIn: true, })); } export async function GET(req: NextRequest) { const base = builtIns(); const auth = await createAuthenticatedClient(req); if (!auth) return Response.json({ files: base, authenticated: false }); const projectId = req.nextUrl.searchParams.get("projectId"); let query = auth.client.from("knowledge_documents").select("id,name,content,project_id,updated_at").order("updated_at", { ascending: false }); query = projectId ? query.or(`project_id.eq.${projectId},project_id.is.null`) : query.is("project_id", null); const { data, error } = await query; if (error) return Response.json({ files: base, authenticated: true, databaseReady: false, warning: error.message }); const privateFiles = (data || []).map((document) => ({ id: document.id, name: document.name, slug: document.name.replace(/\.(md|txt)$/i, ""), sizeBytes: Buffer.byteLength(document.content), words: document.content.split(/\s+/).length, preview: document.content.slice(0, 180).replace(/\n/g, " "), modifiedAt: document.updated_at, projectId: document.project_id, builtIn: false, })); return Response.json({ files: [...privateFiles, ...base], authenticated: true, databaseReady: true }); } export async function POST(req: NextRequest) { const auth = await createAuthenticatedClient(req); if (!auth) return Response.json({ error: "Sign in to create private knowledge files." }, { status: 401 }); const { name, content, projectId = null } = await req.json(); if (!name?.trim() || !content?.trim()) return Response.json({ error: "Missing name or content" }, { status: 400 }); const safeName = name.trim().replace(/[^\p{L}\p{N}_. -]/gu, "_").slice(0, 120); const { data, error } = await auth.client.from("knowledge_documents").insert({ owner_id: auth.user.id, project_id: projectId || null, name: /\.(md|txt)$/i.test(safeName) ? safeName : `${safeName}.md`, content: content.slice(0, 500000), }).select("id,name").single(); if (error) return Response.json({ error: error.message, migrationRequired: error.code === "42P01" }, { status: 500 }); return Response.json({ success: true, file: data }); } export async function DELETE(req: NextRequest) { const auth = await createAuthenticatedClient(req); if (!auth) return Response.json({ error: "Sign in required." }, { status: 401 }); const { id } = await req.json(); if (!id || String(id).startsWith("builtin-")) return Response.json({ error: "Built-in files cannot be deleted." }, { status: 400 }); const { error } = await auth.client.from("knowledge_documents").delete().eq("id", id); if (error) return Response.json({ error: error.message }, { status: 500 }); return Response.json({ success: true }); }