115 lines
4.0 KiB
JavaScript
115 lines
4.0 KiB
JavaScript
// background.js — Service Worker for Claude Arabic Voice
|
|
// Handles Gemini API calls for voice text processing via the existing server proxy
|
|
|
|
const SERVER_URL = 'https://cv.intaleqapp.com/cv/server/generate_cv.php';
|
|
|
|
// ─── Message Listener ────────────────────────────────────────────────────────
|
|
|
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
if (message.type === 'GEMINI_PROCESS_VOICE') {
|
|
handleVoiceProcessing(message.payload)
|
|
.then(result => sendResponse({ success: true, data: result }))
|
|
.catch(err => sendResponse({ success: false, error: err.message }));
|
|
return true; // Keep message channel open for async
|
|
}
|
|
});
|
|
|
|
// ─── Voice Text Processing with Gemini (via server proxy) ────────────────────
|
|
|
|
async function handleVoiceProcessing({ apiKey, model, text, language }) {
|
|
if (!apiKey) {
|
|
throw new Error('Gemini API key is required');
|
|
}
|
|
|
|
// Detect if text is Arabic
|
|
const isArabic = /[\u0600-\u06FF]/.test(text);
|
|
const langName = isArabic ? 'Arabic' : 'the detected language';
|
|
|
|
const prompt = `You are a text refinement assistant. Your task is to:
|
|
|
|
1. Correct any speech recognition errors in the following text
|
|
2. Fix punctuation, capitalization, and formatting
|
|
3. Keep the original meaning and content intact
|
|
4. Do NOT add any new information or commentary
|
|
5. Return ONLY the corrected text, nothing else
|
|
|
|
The text is in ${langName}. Preserve the original language.
|
|
|
|
TEXT TO REFINE:
|
|
${text}
|
|
|
|
CORRECTED TEXT:`;
|
|
|
|
console.log('[ClaudeVoice] Sending to server:', SERVER_URL);
|
|
|
|
const response = await fetch(SERVER_URL, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
action: 'generateText',
|
|
apiKey: apiKey,
|
|
prompt: prompt
|
|
})
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errText = await response.text().catch(() => '');
|
|
let errMsg;
|
|
try {
|
|
const errData = JSON.parse(errText);
|
|
errMsg = errData.error?.message || `HTTP ${response.status}`;
|
|
} catch (e) {
|
|
errMsg = `HTTP ${response.status}: ${errText.substring(0, 200)}`;
|
|
}
|
|
throw new Error(`Gemini API error: ${errMsg}`);
|
|
}
|
|
|
|
const responseText = await response.text();
|
|
console.log('[ClaudeVoice] Server response received, length:', responseText.length);
|
|
|
|
// Try to parse as JSON (Gemini response format from server proxy)
|
|
let data;
|
|
try {
|
|
data = JSON.parse(responseText);
|
|
} catch (e) {
|
|
// If not JSON, use the raw text
|
|
return { text: responseText.trim() };
|
|
}
|
|
|
|
// Check if it's a Gemini API response format
|
|
if (data.candidates && data.candidates[0]) {
|
|
const resultText = data.candidates[0].content?.parts?.[0]?.text;
|
|
if (resultText) {
|
|
return { text: resultText.trim() };
|
|
}
|
|
}
|
|
|
|
// Check if it's our server's error format
|
|
if (data.error) {
|
|
throw new Error(`Server error: ${data.error}${data.details ? ' - ' + JSON.stringify(data.details) : ''}`);
|
|
}
|
|
|
|
// If we got here but have some text, return it
|
|
if (typeof data === 'string') {
|
|
return { text: data.trim() };
|
|
}
|
|
|
|
throw new Error('Empty response from Gemini API');
|
|
}
|
|
|
|
// ─── Installation Handler ────────────────────────────────────────────────────
|
|
|
|
chrome.runtime.onInstalled.addListener((details) => {
|
|
if (details.reason === 'install') {
|
|
// Set default settings
|
|
chrome.storage.sync.set({
|
|
language: 'ar-SA',
|
|
autoSend: false,
|
|
useGemini: false,
|
|
geminiApiKey: '',
|
|
geminiModel: 'gemini-flash-lite-latest'
|
|
});
|
|
console.log('[ClaudeVoice] ✅ Extension installed with default settings');
|
|
}
|
|
});
|