gaurv007 commited on
Commit
682ea26
Β·
verified Β·
1 Parent(s): 475b227

fix(extension): correct API_BASE URL to Netlify web app, store session_id, fix async sidePanel, clean up CRITICAL severity

Browse files
Files changed (1) hide show
  1. extension/background.js +47 -17
extension/background.js CHANGED
@@ -1,13 +1,19 @@
1
  /**
2
- * ClauseGuard β€” Background Service Worker v3.0
3
- * FIXED: API payload now sends {text, source_url} (not {clauses})
4
- * FIXED: Error handling and retry logic
 
 
 
5
  */
6
 
7
- // FIX v4.2: Corrected API_BASE URL to match the actual Gradio Space
8
- const API_BASE = "https://gaurv007-clauseguard.hf.space";
 
 
 
9
  const FREE_SCANS_PER_MONTH = 10;
10
- const API_TIMEOUT_MS = 45000;
11
 
12
  const SITE_ORIGINS = [
13
  "https://clauseguardweb.netlify.app",
@@ -34,10 +40,15 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
34
  case "GET_AUTH": return await getAuth();
35
  case "GET_USER": return await getUser();
36
  case "CHECK_USAGE": return await checkUsage();
37
- case "OPEN_SIDEPANEL": if (sender.tab?.id) chrome.sidePanel.open({ tabId: sender.tab.id }); return { ok: true };
 
 
 
 
38
  case "GET_RESULTS": return await getStoredResults(sender.tab?.id || message.tabId);
39
  case "SYNC_AUTH": return await syncAuthFromWebsite();
40
  case "GET_SCAN_HISTORY": return await getScanHistory();
 
41
  default: return null;
42
  }
43
  };
@@ -95,7 +106,8 @@ async function handleAnalyze(payload, tabId) {
95
  let results;
96
  try {
97
  const auth = await getAuth();
98
- // FIXED: Send {text, source_url} not {clauses}
 
99
  const resp = await fetchWithTimeout(`${API_BASE}/api/analyze`, {
100
  method: "POST",
101
  headers: {
@@ -109,9 +121,17 @@ async function handleAnalyze(payload, tabId) {
109
  return { error: "rate_limited", message: "Too many requests. Please wait a moment." };
110
  }
111
 
112
- if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
113
- results = await resp.json();
114
- results.source = "api";
 
 
 
 
 
 
 
 
115
  } catch (err) {
116
  console.warn("API unavailable, using local:", err.message);
117
  results = localAnalyze(text);
@@ -121,6 +141,12 @@ async function handleAnalyze(payload, tabId) {
121
  // Store results
122
  if (tabId) {
123
  await chrome.storage.local.set({ [`results_${tabId}`]: results });
 
 
 
 
 
 
124
  const flagged = results.results?.filter(r => r.categories?.length > 0).length || results.flagged_count || 0;
125
  chrome.action.setBadgeText({ text: flagged > 0 ? String(flagged) : "", tabId });
126
  if (flagged > 0) chrome.action.setBadgeBackgroundColor({ color: flagged > 3 ? "#ef4444" : "#f59e0b", tabId });
@@ -152,6 +178,12 @@ async function getScanHistory() {
152
  return { history: scanHistory };
153
  }
154
 
 
 
 
 
 
 
155
  // ─── Sync auth from website ───
156
  async function syncAuthFromWebsite() {
157
  return await getAuth();
@@ -182,14 +214,12 @@ function localAnalyze(text) {
182
  });
183
 
184
  const flagged = results.filter(r => r.categories.length > 0);
185
- const sev = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 };
186
  flagged.forEach(r => r.categories.forEach(c => {
187
  if (sev.hasOwnProperty(c.severity)) sev[c.severity]++;
188
- else sev.MEDIUM++; // default for unknown severity
189
  }));
190
- // FIX v4.2: Use the same diminishing-returns formula as the backend (app.py)
191
- // instead of normalizing by clause count (which gave different scores)
192
- const weighted = sev.CRITICAL*40 + sev.HIGH*20 + sev.MEDIUM*10 + sev.LOW*3;
193
  const risk = Math.min(100, Math.round(100 * (1 - (1 / (1 + weighted / 30)))));
194
 
195
  return {
@@ -245,4 +275,4 @@ async function getStoredResults(tabId) {
245
  return new Promise(r => chrome.storage.local.get([`results_${tabId}`], d => r(d[`results_${tabId}`]||null)));
246
  }
247
 
248
- chrome.tabs.onRemoved.addListener(tabId => chrome.storage.local.remove([`results_${tabId}`]));
 
1
  /**
2
+ * ClauseGuard β€” Background Service Worker v4.3
3
+ * FIXED v4.3: API_BASE now routes through the Netlify web app which has
4
+ * proper Gradio SSE polling logic. The old URL pointed at the Gradio Space
5
+ * directly, which doesn't expose a REST /api/analyze endpoint.
6
+ * FIXED v4.3: session_id from analyze response is now stored so chat can use it.
7
+ * FIXED v4.3: sidePanel.open() is properly awaited.
8
  */
9
 
10
+ // FIX v4.3: Route through the Netlify web app β€” it already has Gradio SSE
11
+ // polling in its /api/analyze route. The extension just needs a REST endpoint.
12
+ // Previously pointed to "https://gaurv007-clauseguard.hf.space" which is a
13
+ // Gradio Space that only exposes /gradio_api/call/analyze (SSE, not REST).
14
+ const API_BASE = "https://clauseguardweb.netlify.app";
15
  const FREE_SCANS_PER_MONTH = 10;
16
+ const API_TIMEOUT_MS = 90000; // Increased to 90s β€” web route polls Gradio which can be slow
17
 
18
  const SITE_ORIGINS = [
19
  "https://clauseguardweb.netlify.app",
 
40
  case "GET_AUTH": return await getAuth();
41
  case "GET_USER": return await getUser();
42
  case "CHECK_USAGE": return await checkUsage();
43
+ case "OPEN_SIDEPANEL":
44
+ if (sender.tab?.id) {
45
+ try { await chrome.sidePanel.open({ tabId: sender.tab.id }); } catch(e) { console.warn("sidePanel.open failed:", e); }
46
+ }
47
+ return { ok: true };
48
  case "GET_RESULTS": return await getStoredResults(sender.tab?.id || message.tabId);
49
  case "SYNC_AUTH": return await syncAuthFromWebsite();
50
  case "GET_SCAN_HISTORY": return await getScanHistory();
51
+ case "GET_SESSION_ID": return await getStoredSessionId(sender.tab?.id || message.tabId);
52
  default: return null;
53
  }
54
  };
 
106
  let results;
107
  try {
108
  const auth = await getAuth();
109
+ // FIX v4.3: Send {text, source_url} to the Netlify web route which
110
+ // handles Gradio SSE polling internally and returns plain JSON.
111
  const resp = await fetchWithTimeout(`${API_BASE}/api/analyze`, {
112
  method: "POST",
113
  headers: {
 
121
  return { error: "rate_limited", message: "Too many requests. Please wait a moment." };
122
  }
123
 
124
+ if (resp.status === 401) {
125
+ // Web route requires auth β€” fall back to local analysis for guests
126
+ console.warn("API returned 401, using local analysis for guest user");
127
+ results = localAnalyze(text);
128
+ results.source = "local";
129
+ } else if (!resp.ok) {
130
+ throw new Error(`HTTP ${resp.status}`);
131
+ } else {
132
+ results = await resp.json();
133
+ results.source = "api";
134
+ }
135
  } catch (err) {
136
  console.warn("API unavailable, using local:", err.message);
137
  results = localAnalyze(text);
 
141
  // Store results
142
  if (tabId) {
143
  await chrome.storage.local.set({ [`results_${tabId}`]: results });
144
+
145
+ // FIX v4.3: Also store session_id so the chat feature can use it
146
+ if (results.session_id) {
147
+ await chrome.storage.local.set({ [`session_${tabId}`]: results.session_id });
148
+ }
149
+
150
  const flagged = results.results?.filter(r => r.categories?.length > 0).length || results.flagged_count || 0;
151
  chrome.action.setBadgeText({ text: flagged > 0 ? String(flagged) : "", tabId });
152
  if (flagged > 0) chrome.action.setBadgeBackgroundColor({ color: flagged > 3 ? "#ef4444" : "#f59e0b", tabId });
 
178
  return { history: scanHistory };
179
  }
180
 
181
+ // ─── Get stored session ID (for chat) ───
182
+ async function getStoredSessionId(tabId) {
183
+ if (!tabId) return null;
184
+ return new Promise(r => chrome.storage.local.get([`session_${tabId}`], d => r(d[`session_${tabId}`] || null)));
185
+ }
186
+
187
  // ─── Sync auth from website ───
188
  async function syncAuthFromWebsite() {
189
  return await getAuth();
 
214
  });
215
 
216
  const flagged = results.filter(r => r.categories.length > 0);
217
+ const sev = { HIGH: 0, MEDIUM: 0, LOW: 0 };
218
  flagged.forEach(r => r.categories.forEach(c => {
219
  if (sev.hasOwnProperty(c.severity)) sev[c.severity]++;
220
+ else sev.MEDIUM++;
221
  }));
222
+ const weighted = sev.HIGH * 20 + sev.MEDIUM * 10 + sev.LOW * 3;
 
 
223
  const risk = Math.min(100, Math.round(100 * (1 - (1 / (1 + weighted / 30)))));
224
 
225
  return {
 
275
  return new Promise(r => chrome.storage.local.get([`results_${tabId}`], d => r(d[`results_${tabId}`]||null)));
276
  }
277
 
278
+ chrome.tabs.onRemoved.addListener(tabId => chrome.storage.local.remove([`results_${tabId}`, `session_${tabId}`]));