ClauseGuard / web /app /api /chat /route.ts
gaurv007's picture
🔧 v4.3: Web app deep audit — 12 bugs fixed (4 critical) (#6)
bf51166
import { NextRequest, NextResponse } from "next/server";
import { createClient } from "@/lib/supabase/server";
/**
* FIX v4.3: Chat route completely rewritten.
*
* ARCHITECTURE:
* The Gradio ChatInterface uses gr.State for RAG embeddings — these are
* per-browser-session and NOT accessible via the Gradio REST API. Every API
* call creates a new session with empty state, so chat via Gradio API will
* NEVER have contract context.
*
* The correct approach:
* 1. PRIMARY: Use the FastAPI backend (/api/chat) which manages RAG sessions
* with proper TTL-based expiry. The session_id comes from /api/analyze.
* 2. FALLBACK: If FastAPI is unavailable, return a clear error directing
* the user to use the Gradio Space directly.
*
* The old code tried to call a non-existent Gradio "chat" endpoint which
* always failed. Removed the broken Gradio fallback entirely.
*/
export async function POST(req: NextRequest) {
try {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
return NextResponse.json({ error: "Unauthorized. Please log in." }, { status: 401 });
}
const body = await req.json();
const { message, history, session_id } = body;
if (!message) {
return NextResponse.json(
{ error: "message is required" },
{ status: 400 }
);
}
if (message.length > 2000) {
return NextResponse.json(
{ error: "Message too long (max 2000 characters)" },
{ status: 400 }
);
}
// Try the FastAPI backend (it has proper RAG session management)
const apiUrl = process.env.CLAUSEGUARD_API_URL || "";
if (apiUrl && session_id) {
try {
const apiRes = await fetch(`${apiUrl}/api/chat`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message, session_id, history: history || [] }),
});
if (apiRes.ok) {
const data = await apiRes.json();
return NextResponse.json({ response: data.response });
}
// If 404, session expired
if (apiRes.status === 404) {
return NextResponse.json({
response: "⚠️ Your chat session has expired (sessions last 1 hour). " +
"Please analyze the contract again to start a new chat session."
});
}
} catch {
// FastAPI backend unreachable — fall through to error message
}
}
// No FastAPI backend available or no session_id
// FIX v4.3: Return a clear, helpful message instead of trying a broken Gradio endpoint
if (!apiUrl) {
return NextResponse.json({
response: "⚠️ Contract Q&A chat requires the FastAPI backend which is not currently deployed. " +
"You can use the chat feature directly in the [Gradio Space](https://gaurv007-clauseguard.hf.space) " +
"— analyze a contract there, then switch to the Q&A tab."
});
}
if (!session_id) {
return NextResponse.json({
response: "⚠️ No active chat session. Please analyze a contract first — " +
"the chat session is created when you run analysis."
});
}
return NextResponse.json({
response: "⚠️ Chat service is temporarily unavailable. Please try again, or use the " +
"[Gradio Space](https://gaurv007-clauseguard.hf.space) directly."
});
} catch (error: any) {
console.error("Chat error:", error.message);
return NextResponse.json(
{ error: error.message || "Chat failed. Make sure you analyzed a contract first." },
{ status: 500 }
);
}
}