// 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'); } });