File size: 4,352 Bytes
e484722
bf51166
e484722
bf51166
 
 
 
 
 
 
 
 
e484722
 
 
bf51166
 
 
 
 
 
 
e484722
 
 
 
 
 
 
 
 
 
bf51166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e484722
bf51166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e484722
 
bf51166
 
 
 
 
e484722
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { NextRequest, NextResponse } from "next/server";
import { createClient } from "@/lib/supabase/server";

/**
 * FIX v4.3: Redline route now works through the Gradio Space directly.
 * The old code pointed to a non-existent FastAPI Space (gaurv007-clauseguard-api.hf.space).
 * Since redlining is already part of the analyze pipeline (returned in analysis results),
 * this endpoint is primarily for re-running redlines on existing text.
 */

const GRADIO_URL = process.env.CLAUSEGUARD_GRADIO_URL || "https://gaurv007-clauseguard.hf.space";
const API_URL = process.env.CLAUSEGUARD_API_URL || "";

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 { session_id, text, use_llm } = body;

    if (!session_id && !text) {
      return NextResponse.json(
        { error: "Provide session_id or text" },
        { status: 400 }
      );
    }

    // Try FastAPI backend first (if configured and available)
    if (API_URL) {
      try {
        const response = await fetch(`${API_URL}/api/redline`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ session_id, text, use_llm: use_llm ?? true }),
        });

        if (response.ok) {
          const result = await response.json();
          return NextResponse.json(result);
        }
      } catch {
        // Fall through to Gradio approach
      }
    }

    // Fallback: If text is provided, run full analysis via Gradio (includes redlines)
    if (text) {
      if (text.trim().length < 50) {
        return NextResponse.json({ error: "Text too short (min 50 chars)" }, { status: 400 });
      }

      const submitRes = await fetch(`${GRADIO_URL}/gradio_api/call/analyze`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ data: [text] }),
      });

      if (!submitRes.ok) {
        throw new Error(`Gradio submit failed: ${submitRes.status}`);
      }

      const { event_id } = await submitRes.json();
      if (!event_id) throw new Error("No event_id from Gradio");

      let resultText = "";
      let attempts = 0;
      while (attempts < 90) {
        const resultRes = await fetch(
          `${GRADIO_URL}/gradio_api/call/analyze/${event_id}`,
          { headers: { Accept: "text/event-stream" } }
        );
        resultText = await resultRes.text();
        if (resultText.includes("event: complete")) break;
        if (resultText.includes("event: error")) throw new Error("Redline analysis failed");
        await new Promise(r => setTimeout(r, 1000));
        attempts++;
      }

      if (!resultText.includes("event: complete")) {
        throw new Error("Analysis timed out");
      }

      // Parse the result to extract redlines from the JSON report
      const completeIdx = resultText.indexOf("event: complete");
      const dataIdx = resultText.indexOf("data: ", completeIdx);
      if (dataIdx === -1) throw new Error("No data in response");

      const dataStr = resultText.substring(dataIdx + 6).trim();
      const gradioData = JSON.parse(dataStr);

      // Download JSON report file
      const jsonFileObj = gradioData[8];
      if (jsonFileObj?.url) {
        const jsonRes = await fetch(jsonFileObj.url);
        if (jsonRes.ok) {
          const analysisData = await jsonRes.json();
          if (analysisData.redlines) {
            return NextResponse.json({ redlines: analysisData.redlines, count: analysisData.redlines.length });
          }
        }
      }

      return NextResponse.json({ redlines: [], count: 0 });
    }

    // No FastAPI backend and only session_id provided (can't access Gradio sessions)
    return NextResponse.json({
      error: "Redline by session_id requires the FastAPI backend. Provide contract text instead, or use the analysis results which already include redline suggestions.",
    }, { status: 400 });

  } catch (error: any) {
    console.error("Redline error:", error.message);
    return NextResponse.json(
      { error: error.message || "Redlining failed" },
      { status: 500 }
    );
  }
}