sbq

🔉Últimos dias para pagar anuidade da SBQ 2026 com mesmo valor da anuidade de 2025 - até 15 de dezembro

Últimos dias para pagar anuidade da SBQ 2026 com mesmo valor da anuidade de 2025 - até 15 de dezembro 

*divulgação

 

Últimos dias para pagar anuidade da SBQ 2026 com mesmo valor da anuidade de 2025 - até 15 de dezembro .


- Acesse e atualize sua contribuição anual em https://sistema.sbq.org.br/pt/login


- Mantida política de descontos progressivos dependendo do tempo de fidelidade e da data de pagamento- Saiba mais em: https://www.sbq.org.br/taxas-sbq-2026/


- Conheça todas as vantagens em ser associado(a) da SBQ em: https://www.sbq.org.br/por-que-se-associar-a-sbq/


📌A 49ª RASBQ (15 a 18 de junho de 2026), tem a campanha “ Minha primeira anuidade SBQ ” para estudantes de mestrado e iniciação científica que frequentem a RASBQ que não possuem cadastro no sistema de sócios da SBQ- terão isenção da anuidade da SBQ 2026.

Importante: não será feito reembolso de anuidade , então nesse caso deve se cadastrar pelo sistema da RASBQ - confira instruções em: https://www.sbq.org.br/49ra/pagina/informacoesinscr.php

Categorias: Notícias

// js/service-worker.js - Service Worker com Tratamento de Erros Robusto, Auto-Evolução e Fallback console.debug('[Lalique] Service Worker: Starting initialization...'); // ===================================================================================== // CRÍTICO: VERIFIQUE ESTES CAMINHOS DE IMPORTAÇÃO! // Eles são relativos ao diretório do service-worker.js (que está em js/) // Certifique-se de que CADA UM DESSES ARQUIVOS EXPORTA A CLASSE CORRESPONDENTE // usando 'export class NomeDaClasse { ... }' // ===================================================================================== import { StorageManager } from './utils/storage.js'; import { OffscreenManager } from './utils/offscreen-manager.js'; import { AIManager } from './modules/ai-module.js'; import { CacheManager } from './utils/cache-manager.js'; import { AutoEvolution } from './modules/auto-evolution.js'; import { FocusModeManager } from './modules/focus-mode.js'; // Adicionado FocusModeManager console.debug('[Lalique] Service Worker: All modules imported successfully.'); // ===================================================================================== // Inicialização das classes // ===================================================================================== const storage = new StorageManager(); const offscreenManager = new OffscreenManager(); // Inicializado const aiManager = new AIManager(); const cacheManager = new CacheManager('ai_cache', 500); const autoEvolution = new AutoEvolution(storage, aiManager); const focusModeManager = new FocusModeManager(storage); // Inicializado FocusModeManager let isProcessing = false; let currentProgress = { value: 0, status: 'Idle' }; console.debug('[Lalique] Service Worker: All managers initialized successfully.'); // ========== INSTALAÇÃO E ATUALIZAÇÃO ========== chrome.runtime.onInstalled.addListener(async (details) => { console.log('[Lalique] Extension installed/updated'); try { if (details.reason === 'install') { await storage.set('firstRun', true); await storage.set('theme', 'jewels'); await storage.set('backgroundProcessingEnabled', true); await storage.set('autoEvolutionEnabled', true); // Ativado por padrão await storage.set('focusModeEnabled', false); await storage.set('turboModeEnabled', true); // Ativado por padrão await storage.set('lazarusModeEnabled', true); // Ativado por padrão await storage.set('autoEvolutionFrequency', 120); // 2 horas await storage.set('healthCheckFrequency', 60); // 1 hora await storage.set('usageStats', { totalOrganizations: 0, totalHealthChecks: 0, totalSearches: 0, linksRecovered: 0, aiOperations: 0, selfHealingEvents: 0 }); await storage.set('userInteractions', []); await storage.set('focusModeBlockedSites', [ 'facebook.com', 'twitter.com', 'instagram.com', 'linkedin.com', 'youtube.com', 'reddit.com' ]); chrome.alarms.create('linkHealthCheck', { periodInMinutes: 60 }); chrome.alarms.create('autoEvolutionCheck', { periodInMinutes: 120 }); console.log('[Lalique] Installation completed'); } else if (details.reason === 'update') { console.log('[Lalique] Extension updated. Checking for migrations...'); // Migrações para novas configurações, se necessário const currentFocusModeEnabled = await storage.get('focusModeEnabled'); if (currentFocusModeEnabled === undefined) { await storage.set('focusModeEnabled', false); } const currentAutoEvolutionEnabled = await storage.get('autoEvolutionEnabled'); if (currentAutoEvolutionEnabled === undefined) { await storage.set('autoEvolutionEnabled', true); } const currentTurboModeEnabled = await storage.get('turboModeEnabled'); if (currentTurboModeEnabled === undefined) { await storage.set('turboModeEnabled', true); } const currentLazarusModeEnabled = await storage.get('lazarusModeEnabled'); if (currentLazarusModeEnabled === undefined) { await storage.set('lazarusModeEnabled', true); } const currentAutoEvolutionFrequency = await storage.get('autoEvolutionFrequency'); if (currentAutoEvolutionFrequency === undefined) { await storage.set('autoEvolutionFrequency', 120); } const currentHealthCheckFrequency = await storage.get('healthCheckFrequency'); if (currentHealthCheckFrequency === undefined) { await storage.set('healthCheckFrequency', 60); } // Limpa e recria alarmes para garantir que as frequências estejam atualizadas chrome.alarms.clearAll(); chrome.alarms.create('linkHealthCheck', { periodInMinutes: await storage.get('healthCheckFrequency') || 60 }); chrome.alarms.create('autoEvolutionCheck', { periodInMinutes: await storage.get('autoEvolutionFrequency') || 120 }); } } catch (error) { console.error('[Lalique] Installation/Update error:', error); autoEvolution.logError('service-worker', 'Installation/Update failed', { error: error.message }); } }); // ========== ALARMES ========== chrome.alarms.onAlarm.addListener(async (alarm) => { console.log(`[Lalique] Alarm triggered: ${alarm.name}`); if (isProcessing && alarm.name !== 'autoEvolutionCheck') { console.log('[Lalique] Already processing, skipping other tasks...'); return; } try { isProcessing = true; currentProgress = { value: 0, status: `Executando ${alarm.name}...` }; await sendProgressUpdate(); switch (alarm.name) { case 'linkHealthCheck': await backgroundLinkHealthCheck(); break; case 'autoEvolutionCheck': const autoEvolutionEnabled = await storage.get('autoEvolutionEnabled'); if (autoEvolutionEnabled) { await autoEvolution.runEvolutionCycle(); } else { console.log('[Lalique] Auto-Evolution is disabled. Skipping cycle.'); } break; case 'focusModeTimer': await focusModeManager.endFocusSession(); showNotification('Modo Foco Finalizado', 'Sua sessão de foco terminou. Você pode navegar livremente agora.', 'info'); break; default: console.warn(`[Lalique] Unknown alarm: ${alarm.name}`); } } catch (error) { console.error(`[Lalique] Error during alarm ${alarm.name}:`, error); autoEvolution.logError('service-worker', `Alarm ${alarm.name} failed`, { error: error.message }); showNotification('❌ Erro de Processamento', `Ocorreu um erro durante a tarefa: ${alarm.name}.`, 'error'); } finally { isProcessing = false; currentProgress = { value: 100, status: 'Concluído' }; await sendProgressUpdate(); currentProgress = { value: 0, status: 'Idle' }; // Reset para o próximo ciclo await sendProgressUpdate(); updateBadge(); } }); // ========== LISTENERS DE MENSAGENS ========== chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { console.log('[Lalique] Message received:', message.action, message.data); // Tratamento de mensagens assíncronas const handleMessage = async () => { try { switch (message.action) { case 'addBookmark': const bookmarkId = await addBookmark(message.data.url, message.data.title, message.data.parentId); sendResponse({ success: true, bookmarkId: bookmarkId }); break; case 'getBookmarkTree': const tree = await getBookmarkTree(); sendResponse({ success: true, tree: tree }); break; case 'searchBookmarks': const results = await searchBookmarks(message.data.query); sendResponse({ success: true, results: results }); break; case 'getBookmarkDetails': const details = await getBookmarkDetails(message.data.id); sendResponse({ success: true, details: details }); break; case 'updateBookmark': await updateBookmark(message.data.id, message.data.changes); sendResponse({ success: true }); break; case 'removeBookmark': await removeBookmark(message.data.id); sendResponse({ success: true }); break; case 'moveBookmark': await moveBookmark(message.data.id, message.data.destination); sendResponse({ success: true }); break; case 'createFolder': const folderId = await createFolder(message.data.title, message.data.parentId); sendResponse({ success: true, folderId: folderId }); break; case 'getUsageStats': const stats = await storage.get('usageStats'); sendResponse({ success: true, stats: stats }); break; case 'getUserInteractions': const interactions = await storage.get('userInteractions'); sendResponse({ success: true, interactions: interactions }); break; case 'logUserInteraction': await logUserInteraction(message.data.type, message.data.details); sendResponse({ success: true }); break; case 'getTheme': const theme = await storage.get('theme'); sendResponse({ success: true, theme: theme }); break; case 'setTheme': await storage.set('theme', message.data.theme); sendResponse({ success: true }); break; case 'getAPIKeys': const keys = await aiManager.getAPIKeys(); sendResponse({ success: true, keys: keys }); break; case 'setAPIKey': await aiManager.setAPIKey(message.data.provider, message.data.key); sendResponse({ success: true }); break; case 'removeAPIKey': await aiManager.removeAPIKey(message.data.provider); sendResponse({ success: true }); break; case 'getAIModels': const models = await aiManager.getAIModels(); sendResponse({ success: true, models: models }); break; case 'setAIModels': await aiManager.setAIModels(message.data.models); sendResponse({ success: true }); break; case 'clearAICache': await cacheManager.clear(); sendResponse({ success: true }); break; case 'getAICacheSettings': const cacheSettings = { duration: await storage.get('aiCacheDuration') || 24 * 60, // default 24h size: cacheManager.getSize() }; sendResponse({ success: true, settings: cacheSettings }); break; case 'setAICacheDuration': await storage.set('aiCacheDuration', message.data.duration); cacheManager.setExpiration(message.data.duration); sendResponse({ success: true }); break; case 'aiAnalyzeSentiment': const sentiment = await aiManager.analyzeSentiment(message.data.text); sendResponse({ success: true, sentiment: sentiment }); break; case 'aiSummarize': const summary = await aiManager.summarizeText(message.data.text); sendResponse({ success: true, summary: summary }); break; case 'aiGenerateTags': const tags = await aiManager.generateTags(message.data.text); sendResponse({ success: true, tags: tags }); break; case 'aiExtractKeywords': const keywords = await aiManager.extractKeywords(message.data.text); sendResponse({ success: true, keywords: keywords }); break; case 'aiCategorize': const category = await aiManager.categorizeText(message.data.text, message.data.categories); sendResponse({ success: true, category: category }); break; case 'aiSemanticSearch': const semanticResults = await aiManager.semanticSearch(message.data.query, message.data.documents); sendResponse({ success: true, results: semanticResults }); break; case 'aiGetEmbeddings': const embeddings = await aiManager.getEmbeddings(message.data.text); sendResponse({ success: true, embeddings: embeddings }); break; case 'getAutoEvolutionSuggestions': const suggestions = await storage.get('autoEvolutionSuggestions') || []; sendResponse({ success: true, suggestions: suggestions }); break; case 'applyAutoEvolutionSuggestion': await autoEvolution.applySuggestion(message.data.suggestionId); sendResponse({ success: true }); break; case 'dismissAutoEvolutionSuggestion': await autoEvolution.dismissSuggestion(message.data.suggestionId); sendResponse({ success: true }); break; case 'getAutoEvolutionSettings': const autoEvolutionSettings = { enabled: await storage.get('autoEvolutionEnabled'), frequency: await storage.get('autoEvolutionFrequency') }; sendResponse({ success: true, settings: autoEvolutionSettings }); break; case 'setAutoEvolutionSettings': await storage.set('autoEvolutionEnabled', message.data.enabled); await storage.set('autoEvolutionFrequency', message.data.frequency); await chrome.alarms.clear('autoEvolutionCheck'); if (message.data.enabled) { chrome.alarms.create('autoEvolutionCheck', { periodInMinutes: message.data.frequency }); } sendResponse({ success: true }); break; case 'getBackgroundProcessingStatus': sendResponse({ success: true, isProcessing: isProcessing, progress: currentProgress }); break; case 'getAdvancedSettings': const advancedSettings = { privateAnalyticsEnabled: await storage.get('privateAnalyticsEnabled'), turboModeEnabled: await storage.get('turboModeEnabled'), lazarusModeEnabled: await storage.get('lazarusModeEnabled'), autoEvolutionFrequency: await storage.get('autoEvolutionFrequency') }; sendResponse({ success: true, settings: advancedSettings }); break; case 'setAdvancedSettings': await storage.set('privateAnalyticsEnabled', message.data.privateAnalyticsEnabled); await storage.set('turboModeEnabled', message.data.turboModeEnabled); await storage.set('lazarusModeEnabled', message.data.lazarusModeEnabled); await storage.set('autoEvolutionFrequency', message.data.autoEvolutionFrequency); await chrome.alarms.clear('autoEvolutionCheck'); chrome.alarms.create('autoEvolutionCheck', { periodInMinutes: message.data.autoEvolutionFrequency }); sendResponse({ success: true }); break; case 'getBiometricStatus': const biometricStatus = await storage.get('biometricAuthEnabled'); sendResponse({ success: true, enabled: biometricStatus }); break; case 'setBiometricStatus': await storage.set('biometricAuthEnabled', message.data.enabled); sendResponse({ success: true }); break; case 'registerBiometricCredential': // Esta ação deve ser tratada no Offscreen Document devido a restrições de WebAuthn const registerResult = await offscreenManager.runOffscreenScript('registerBiometricCredential', message.data); sendResponse(registerResult); break; case 'authenticateBiometricCredential': // Esta ação deve ser tratada no Offscreen Document const authResult = await offscreenManager.runOffscreenScript('authenticateBiometricCredential', message.data); sendResponse(authResult); break; case 'removeBiometricCredential': const removeResult = await offscreenManager.runOffscreenScript('removeBiometricCredential', message.data); sendResponse(removeResult); break; case 'showNotification': // Mensagem para exibir notificação na UI // Esta é uma mensagem para a UI, o SW apenas a retransmite ou a loga se a UI não estiver ativa console.log(`[Lalique] SW received UI notification request: ${message.title} - ${message.message}`); // A UI já tem sua própria função showNotification, então o SW não precisa fazer nada aqui além de logar. sendResponse({ success: true }); break; case 'updateAlarms': await chrome.alarms.clear('linkHealthCheck'); await chrome.alarms.clear('autoEvolutionCheck'); chrome.alarms.create('linkHealthCheck', { periodInMinutes: message.data.healthFrequency }); chrome.alarms.create('autoEvolutionCheck', { periodInMinutes: message.data.evolutionFrequency }); sendResponse({ success: true }); break; case 'startFocusSession': await focusModeManager.startFocusSession(message.data.duration); sendResponse({ success: true }); break; case 'endFocusSession': await focusModeManager.endFocusSession(); sendResponse({ success: true }); break; case 'getFocusModeStatus': const focusStatus = await focusModeManager.getStatus(); sendResponse({ success: true, status: focusStatus }); break; case 'addBlockedSite': await focusModeManager.addBlockedSite(message.data.site); sendResponse({ success: true }); break; case 'removeBlockedSite': await focusModeManager.removeBlockedSite(message.data.site); sendResponse({ success: true }); break; case 'getBlockedSites': const blockedSites = await focusModeManager.getBlockedSites(); sendResponse({ success: true, sites: blockedSites }); break; case 'getHistory': const history = await getBrowserHistory(message.data.startTime, message.data.endTime, message.data.maxResults); sendResponse({ success: true, history: history }); break; default: console.warn('[Lalique] Unknown message action:', message.action); sendResponse({ success: false, error: 'Unknown action' }); } } catch (error) { console.error(`[Lalique] Error handling message action ${message.action}:`, error); autoEvolution.logError('service-worker', `Message handler for ${message.action} failed`, { error: error.message, data: message.data }); sendResponse({ success: false, error: error.message }); } }; // Retorna true para indicar que sendResponse será chamado assincronamente handleMessage(); return true; }); // ========== FUNÇÕES DE BOOKMARKS ========== async function addBookmark(url, title, parentId = '1') { try { const bookmark = await chrome.bookmarks.create({ parentId, title, url }); await logUserInteraction('bookmark_added', { url, title, parentId }); await updateUsageStats('totalOrganizations', 1); console.log('[Lalique] Bookmark added:', bookmark); return bookmark.id; } catch (error) { console.error('[Lalique] Error adding bookmark:', error); autoEvolution.logError('service-worker', 'Add bookmark failed', { url, title, parentId, error: error.message }); throw error; } } async function getBookmarkTree() { try { const tree = await chrome.bookmarks.getTree(); return tree; } catch (error) { console.error('[Lalique] Error getting bookmark tree:', error); autoEvolution.logError('service-worker', 'Get bookmark tree failed', { error: error.message }); throw error; } } async function searchBookmarks(query) { try { const results = await chrome.bookmarks.search(query); await updateUsageStats('totalSearches', 1); return results; } catch (error) { console.error('[Lalique] Error searching bookmarks:', error); autoEvolution.logError('service-worker', 'Search bookmarks failed', { query, error: error.message }); throw error; } } async function getBookmarkDetails(id) { try { const [bookmark] = await chrome.bookmarks.get(id); return bookmark; } catch (error) { console.error('[Lalique] Error getting bookmark details:', error); autoEvolution.logError('service-worker', 'Get bookmark details failed', { id, error: error.message }); throw error; } } async function updateBookmark(id, changes) { try { const bookmark = await chrome.bookmarks.update(id, changes); await logUserInteraction('bookmark_updated', { id, changes }); console.log('[Lalique] Bookmark updated:', bookmark); return bookmark; } catch (error) { console.error('[Lalique] Error updating bookmark:', error); autoEvolution.logError('service-worker', 'Update bookmark failed', { id, changes, error: error.message }); throw error; } } async function removeBookmark(id) { try { await chrome.bookmarks.remove(id); await logUserInteraction('bookmark_removed', { id }); console.log('[Lalique] Bookmark removed:', id); } catch (error) { console.error('[Lalique] Error removing bookmark:', error); autoEvolution.logError('service-worker', 'Remove bookmark failed', { id, error: error.message }); throw error; } } async function moveBookmark(id, destination) { try { const bookmark = await chrome.bookmarks.move(id, destination); await logUserInteraction('bookmark_moved', { id, destination }); console.log('[Lalique] Bookmark moved:', bookmark); return bookmark; } catch (error) { console.error('[Lalique] Error moving bookmark:', error); autoEvolution.logError('service-worker', 'Move bookmark failed', { id, destination, error: error.message }); throw error; } } async function createFolder(title, parentId = '1') { try { const folder = await chrome.bookmarks.create({ parentId, title, url: undefined }); await logUserInteraction('folder_created', { title, parentId }); await updateUsageStats('totalOrganizations', 1); console.log('[Lalique] Folder created:', folder); return folder.id; } catch (error) { console.error('[Lalique] Error creating folder:', error); autoEvolution.logError('service-worker', 'Create folder failed', { title, parentId, error: error.message }); throw error; } } // ========== FUNÇÕES DE HEALTH CHECK DE LINKS ========== async function backgroundLinkHealthCheck() { console.log('[Lalique] Starting background link health check...'); const allBookmarks = await getBookmarkTree(); const flatBookmarks = flattenBookmarks(allBookmarks); const checkPromises = []; let checkedCount = 0; for (const bookmark of flatBookmarks) { if (bookmark.url) { checkPromises.push((async () => { try { const response = await fetch(bookmark.url, { method: 'HEAD', mode: 'no-cors', signal: AbortSignal.timeout(10000) }); if (!response.ok) { console.warn(`[Lalique] Link broken: ${bookmark.url} (Status: ${response.status})`); await storage.set(`link_error_${bookmark.id}`, { url: bookmark.url, status: response.status, timestamp: Date.now() }); // Tentar recuperação com Wayback Machine ou Google Cache const recoveredUrl = await recoverLink(bookmark.url); if (recoveredUrl) { await storage.set(`link_recovered_${bookmark.id}`, { originalUrl: bookmark.url, recoveredUrl: recoveredUrl, timestamp: Date.now() }); await updateUsageStats('linksRecovered', 1); showNotification('🔗 Link Recuperado!', `O link "${bookmark.title}" foi recuperado para: ${recoveredUrl}`, 'success'); } } else { await storage.remove(`link_error_${bookmark.id}`); } } catch (error) { console.warn(`[Lalique] Link check failed for ${bookmark.url}:`, error); await storage.set(`link_error_${bookmark.id}`, { url: bookmark.url, status: 'network_error', timestamp: Date.now(), message: error.message }); const recoveredUrl = await recoverLink(bookmark.url); if (recoveredUrl) { await storage.set(`link_recovered_${bookmark.id}`, { originalUrl: bookmark.url, recoveredUrl: recoveredUrl, timestamp: Date.now() }); await updateUsageStats('linksRecovered', 1); showNotification('🔗 Link Recuperado!', `O link "${bookmark.title}" foi recuperado para: ${recoveredUrl}`, 'success'); } } finally { checkedCount++; currentProgress.value = Math.round((checkedCount / flatBookmarks.length) * 100); currentProgress.status = `Verificando links: ${checkedCount}/${flatBookmarks.length}`; await sendProgressUpdate(); } })()); } } await Promise.allSettled(checkPromises); await updateUsageStats('totalHealthChecks', 1); console.log('[Lalique] Background link health check finished.'); showNotification('✅ Verificação de Links Concluída', 'Todos os seus links foram verificados em segundo plano.', 'info'); updateBadge(); } function flattenBookmarks(bookmarkNodes) { const bookmarks = []; function recurse(nodes) { for (const node of nodes) { if (node.url) { bookmarks.push(node); } if (node.children) { recurse(node.children); } } } recurse(bookmarkNodes); return bookmarks; } async function recoverLink(originalUrl) { const lazarusModeEnabled = await storage.get('lazarusModeEnabled'); if (!lazarusModeEnabled) { console.log('[Lalique] Lazarus Mode is disabled. Skipping link recovery.'); return null; } try { // Tentar Wayback Machine const waybackUrl = `https://archive.org/wayback/available?url=${originalUrl}`; const waybackResponse = await fetch(waybackUrl, { signal: AbortSignal.timeout(5000) }); const waybackData = await waybackResponse.json(); if (waybackData.archived_snapshots && waybackData.archived_snapshots.closest) { console.log('[Lalique] Link recovered via Wayback Machine:', waybackData.archived_snapshots.closest.url); return waybackData.archived_snapshots.closest.url; } } catch (error) { console.warn('[Lalique] Wayback Machine recovery failed:', error); } try { // Tentar Google Cache const googleCacheUrl = `https://webcache.googleusercontent.com/search?q=cache:${originalUrl}`; const googleCacheResponse = await fetch(googleCacheUrl, { method: 'HEAD', signal: AbortSignal.timeout(5000) }); if (googleCacheResponse.ok) { console.log('[Lalique] Link recovered via Google Cache:', googleCacheUrl); return googleCacheUrl; } } catch (error) { console.warn('[Lalique] Google Cache recovery failed:', error); } return null; } // ========== UTILIDADES GERAIS ========== async function updateUsageStats(key, increment = 1) { try { const stats = await storage.get('usageStats') || {}; stats[key] = (stats[key] || 0) + increment; await storage.set('usageStats', stats); } catch (error) { console.error('[Lalique] Error updating usage stats:', error); autoEvolution.logError('service-worker', 'Update usage stats failed', { key, increment, error: error.message }); } } async function logUserInteraction(type, details) { try { const interactions = await storage.get('userInteractions') || []; interactions.push({ timestamp: Date.now(), type, details }); // Manter um limite para não sobrecarregar o storage if (interactions.length > 1000) { interactions.shift(); // Remove o mais antigo } await storage.set('userInteractions', interactions); } catch (error) { console.error('[Lalique] Error logging user interaction:', error); autoEvolution.logError('service-worker', 'Log user interaction failed', { type, details, error: error.message }); } } async function sendProgressUpdate() { try { await chrome.runtime.sendMessage({ action: 'updateProgress', progress: currentProgress }); } catch (error) { // console.warn('[Lalique] Could not send progress update to UI. UI might be closed.', error); // Não logar como erro crítico, pois a UI pode estar fechada } } async function getBrowserHistory(startTime, endTime, maxResults) { try { const historyItems = await chrome.history.search({ text: '', startTime: startTime, endTime: endTime, maxResults: maxResults }); return { success: true, data: historyItems }; } catch (error) { console.error('[Lalique] Error getting browser history:', error); autoEvolution.logError('service-worker', 'Getting browser history failed', { error: error.message }); throw error; } } async function updateBadge() { try { const allErrors = await storage.getAllKeys('link_error_'); const errorsCount = allErrors.length; if (errorsCount > 0) { chrome.action.setBadgeText({ text: errorsCount.toString() }); chrome.action.setBadgeBackgroundColor({ color: '#ef4444' }); } else { chrome.action.setBadgeText({ text: '' }); } const hasKey = await aiManager.hasAnyAPIKey(); if (!hasKey) { chrome.action.setBadgeBackgroundColor({ color: '#f59e0b' }); chrome.action.setBadgeText({ text: '!' }); } else { if (errorsCount === 0) { // Se não há erros, mas há chave, remove o badge '!' chrome.action.setBadgeText({ text: '' }); } } const evolutionSuggestions = await storage.get('autoEvolutionSuggestions') || []; if (evolutionSuggestions.length > 0) { chrome.action.setBadgeBackgroundColor({ color: '#3b82f6' }); chrome.action.setBadgeText({ text: 'AI' }); } } catch (error) { console.error('[Lalique] Error updating badge:', error); autoEvolution.logError('service-worker', 'Badge update failed', { error: error.message }); } } function showNotification(title, message, type = 'info') { chrome.runtime.sendMessage({ action: 'showNotification', title: title, message: message, type: type }).catch(() => { console.warn('[Lalique] Could not send notification to UI. UI might be closed.'); }); } console.log('[Lalique] Service Worker: Script execution finished. Attempting to register.'); updateBadge();