-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.ts
More file actions
188 lines (166 loc) · 5.51 KB
/
background.ts
File metadata and controls
188 lines (166 loc) · 5.51 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Define types inline since we can't use modules in service worker
interface ExaSearchResult {
title: string;
url: string;
publishedDate?: string;
score: number;
highlights: string[];
}
interface VerifyClaimRequest {
type: 'VERIFY_CLAIM';
claim: {
id: number;
text: string;
context: {
page: number;
paragraph: number;
};
relevance: number;
};
}
interface Settings {
exaKey: string;
openaiKey: string;
highlightsEnabled: boolean;
sidebarEnabled: boolean;
darkMode: boolean;
excludedDomains: string[];
maxVerificationsPerDay: number;
enableCaching: boolean;
cacheDuration: number;
useLLMExtraction: boolean;
usageCount: number;
lastUsageReset: number;
}
interface ClaimCache {
timestamp: number;
results: ExaSearchResult[];
}
// Import settings manager using path aliases
import {
initializeSettings,
checkAndResetDailyUsage,
getSettings,
isDailyLimitExceeded,
incrementUsageCounter,
getCachedResults,
cacheResults,
cleanupExpiredCache
} from '@utils/settingsManager';
// Ensure service worker activates
console.log('Background service worker starting...');
// Basic background service worker
chrome.runtime.onInstalled.addListener(() => {
console.log('Extension installed');
// Initialize settings with defaults if needed
initializeSettings();
});
// The Exa API key will be retrieved from storage in the verifyClaimWithExa function
const EXA_API_URL = 'https://api.exa.ai/search';
/**
* Verify a claim using Exa's API to find supporting sources
* This is the core function that connects claims to reliable sources
*
* @param claim - The text of the claim to verify
* @returns Promise resolving to an array of search results with source information
*/
async function verifyClaimWithExa(claim: string): Promise<ExaSearchResult[]> {
try {
// First check for a new day to potentially reset usage counter
await checkAndResetDailyUsage();
// Get settings
const settings = await getSettings();
const { exaKey } = settings;
if (!exaKey) {
throw new Error('Exa API key not found. Please set it in the extension options.');
}
// Check if user has reached daily limit
if (await isDailyLimitExceeded()) {
const maxVerificationsPerDay = settings.maxVerificationsPerDay;
throw new Error(`Daily verification limit (${maxVerificationsPerDay}) reached. Please try again tomorrow.`);
}
// Check cache first
const cachedResults = await getCachedResults(claim);
if (cachedResults) {
return cachedResults;
}
// Send the claim to Exa API as a neural search query
// This uses semantic understanding rather than just keyword matching
const response = await fetch(EXA_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${exaKey}`
},
body: JSON.stringify({
query: claim,
numResults: 3, // Limit to 3 sources for UI simplicity
type: 'neural' // Use neural search for better semantic understanding
})
});
if (!response.ok) {
throw new Error(`Exa API error: ${response.status}`);
}
const data = await response.json();
const results = data.results;
// Update usage counter
await incrementUsageCounter();
// Cache the results
await cacheResults(claim, results);
return results;
} catch (error) {
console.error('Error verifying claim:', error);
throw error;
}
}
// Listen for messages from content script
// This handles the communication between the content script (UI) and background service worker (API calls)
chrome.runtime.onMessage.addListener((
request: VerifyClaimRequest,
sender: chrome.runtime.MessageSender,
sendResponse: (response?: any) => void
) => {
if (request.type === 'VERIFY_CLAIM') {
// Process the claim verification request
// This keeps API calls in the background script for better security and performance
verifyClaimWithExa(request.claim.text)
.then(results => {
console.log('Verification results:', results);
sendResponse({ success: true, results });
})
.catch(error => {
// Check if this is a daily limit error
if (error.message && error.message.includes('Daily verification limit')) {
console.warn('Daily limit reached:', error.message);
sendResponse({
success: false,
error: 'DAILY_LIMIT_REACHED',
message: error.message,
results: []
});
} else {
// Handle other API errors gracefully by returning an empty results array
console.error('Verification failed:', error);
sendResponse({ success: false, error: 'API_ERROR', results: [] });
}
});
return true; // Return true to indicate we'll respond asynchronously
} else if (request.type === 'GET_USAGE_STATS') {
// Return current usage statistics
getSettings().then(settings => {
sendResponse({
success: true,
usageCount: settings.usageCount || 0,
maxVerificationsPerDay: settings.maxVerificationsPerDay || 10,
lastUsageReset: settings.lastUsageReset || Date.now()
});
});
return true;
}
return true; // Always return true from the listener
});
// No need for additional import as we already imported cleanupExpiredCache above
// Run cache cleanup once a day
setInterval(cleanupExpiredCache, 24 * 60 * 60 * 1000); // Every 24 hours
// Also run cleanup when extension starts
cleanupExpiredCache();