// Native messaging removed - using remote server only // import { initNativeHostListener } from './native-host'; // Temporarily disable semantic similarity to focus on connection issues // import { // initSemanticSimilarityListener, // initializeSemanticEngineIfCached, // } from './semantic-similarity'; import { initStorageManagerListener } from './storage-manager'; import { cleanupModelCache } from '@/utils/semantic-similarity-engine'; import { RemoteServerClient } from '@/utils/remote-server-client'; import { DEFAULT_CONNECTION_CONFIG } from '@/common/env-config'; import { handleCallTool } from './tools'; // Global remote server client instance let remoteServerClient: RemoteServerClient | null = null; /** * Background script entry point * Initializes all background services and listeners */ export default defineBackground(() => { // Initialize remote server client first (prioritize over native messaging) initRemoteServerClient(); // Initialize core services (native messaging removed) // initNativeHostListener(); // initSemanticSimilarityListener(); initStorageManagerListener(); // Initialize browser event listeners for connection persistence initBrowserEventListeners(); // Conditionally initialize semantic similarity engine if model cache exists // initializeSemanticEngineIfCached() // .then((initialized) => { // if (initialized) { // console.log('Background: Semantic similarity engine initialized from cache'); // } else { // console.log( // 'Background: Semantic similarity engine initialization skipped (no cache found)', // ); // } // }) // .catch((error) => { // console.warn('Background: Failed to conditionally initialize semantic engine:', error); // }); // Initial cleanup on startup cleanupModelCache().catch((error) => { console.warn('Background: Initial cache cleanup failed:', error); }); }); /** * Initialize remote server client (without auto-connecting) */ function initRemoteServerClient() { try { remoteServerClient = new RemoteServerClient({ serverUrl: DEFAULT_CONNECTION_CONFIG.serverUrl, reconnectInterval: DEFAULT_CONNECTION_CONFIG.reconnectInterval, maxReconnectAttempts: 50, // Increased for better reliability }); console.log('Background: Remote server client initialized (not connected)'); console.log('Background: Use popup to manually connect to remote server'); } catch (error) { console.error('Background: Failed to initialize remote server client:', error); } } /** * Get the remote server client instance */ export function getRemoteServerClient(): RemoteServerClient | null { return remoteServerClient; } /** * Initialize browser event listeners for connection persistence */ function initBrowserEventListeners() { // Listen for browser startup events chrome.runtime.onStartup.addListener(() => { console.log('Background: Browser startup detected. Manual connection required via popup.'); if (remoteServerClient) { console.log('Background: Remote server client ready for manual connection'); } }); // Listen for extension installation/update events chrome.runtime.onInstalled.addListener((details) => { console.log('Background: Extension installed/updated:', details.reason); if (details.reason === 'update') { console.log('Background: Extension updated, manual connection required'); } }); // Listen for browser suspension/resume events (Chrome specific) if (chrome.runtime.onSuspend) { chrome.runtime.onSuspend.addListener(() => { console.log('Background: Browser suspending, connection state saved'); // Connection state is automatically saved when connected }); } if (chrome.runtime.onSuspendCanceled) { chrome.runtime.onSuspendCanceled.addListener(() => { console.log('Background: Browser suspend canceled, maintaining connection'); }); } // Monitor tab events to ensure connection persists across tab operations chrome.tabs.onActivated.addListener((activeInfo) => { // Connection should persist regardless of tab switches if (remoteServerClient && remoteServerClient.isConnected()) { console.log(`Background: Tab switched to ${activeInfo.tabId}, connection maintained`); } }); // Monitor window events chrome.windows.onFocusChanged.addListener((windowId) => { // Connection should persist regardless of window focus changes if ( remoteServerClient && remoteServerClient.isConnected() && windowId !== chrome.windows.WINDOW_ID_NONE ) { console.log(`Background: Window focus changed to ${windowId}, connection maintained`); } }); console.log('Background: Browser event listeners initialized for connection persistence'); // Start periodic connection health check startConnectionHealthCheck(); } /** * Start periodic connection health check to maintain persistent connections */ function startConnectionHealthCheck() { // Check connection health every 5 minutes (for monitoring only, no auto-reconnection) setInterval( () => { if (remoteServerClient) { const isConnected = remoteServerClient.isConnected(); console.log(`Background: Connection health check - Connected: ${isConnected}`); if (!isConnected) { console.log('Background: Connection lost. Use popup to manually reconnect.'); // No automatic reconnection - user must manually reconnect via popup } } }, 5 * 60 * 1000, ); // 5 minutes console.log( 'Background: Connection health check started (monitoring only, no auto-reconnection)', ); } /** * Handle messages from popup for remote server control */ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'getRemoteServerStatus') { const status = remoteServerClient?.getStatus() || { connected: false, connecting: false, reconnectAttempts: 0, connectionTime: undefined, serverUrl: DEFAULT_CONNECTION_CONFIG.serverUrl, }; sendResponse(status); return true; } if (message.type === 'connectRemoteServer') { if (!remoteServerClient) { sendResponse({ success: false, error: 'Remote server client not initialized' }); return true; } if (remoteServerClient.isConnected()) { sendResponse({ success: true, message: 'Already connected' }); return true; } console.log('Background: Attempting to connect to remote server...'); remoteServerClient .connect() .then(() => { console.log('Background: Successfully connected to remote server'); sendResponse({ success: true }); }) .catch((error) => { console.error('Background: Failed to connect to remote server:', error); sendResponse({ success: false, error: error.message }); }); return true; } if (message.type === 'disconnectRemoteServer') { if (!remoteServerClient) { sendResponse({ success: false, error: 'Remote server client not initialized' }); return true; } console.log('Background: Disconnecting from remote server...'); try { remoteServerClient.disconnect(); console.log('Background: Successfully disconnected from remote server'); sendResponse({ success: true }); } catch (error) { console.error('Background: Error during disconnect:', error); sendResponse({ success: false, error: error instanceof Error ? error.message : 'Disconnect failed', }); } return true; } if (message.type === 'restoreRemoteConnection') { if (!remoteServerClient) { sendResponse({ success: false, error: 'Remote server client not initialized' }); return true; } if (remoteServerClient.isConnected()) { sendResponse({ success: true, message: 'Already connected' }); return true; } console.log('Background: Attempting to restore previous connection...'); remoteServerClient .restoreConnectionFromState() .then((restored) => { if (restored) { console.log('Background: Successfully restored previous connection'); sendResponse({ success: true }); } else { console.log('Background: No previous connection to restore'); sendResponse({ success: false, error: 'No previous connection found' }); } }) .catch((error) => { console.error('Background: Failed to restore previous connection:', error); sendResponse({ success: false, error: error.message }); }); return true; } if (message.type === 'getCurrentUserId') { if (!remoteServerClient) { sendResponse({ success: false, error: 'Remote server client not initialized' }); return true; } remoteServerClient .getCurrentUserId() .then((userId) => { sendResponse({ success: true, userId }); }) .catch((error) => { console.error('Background: Failed to get current user ID:', error); sendResponse({ success: false, error: error.message }); }); return true; } if (message.type === 'callTool') { handleCallTool({ name: message.toolName, args: message.params }) .then((result) => { sendResponse(result); }) .catch((error) => { sendResponse({ error: error.message }); }); return true; } if (message.type === 'injectUserIdHelper') { injectUserIdHelper(message.tabId) .then((result) => { sendResponse(result); }) .catch((error) => { sendResponse({ success: false, error: error.message }); }); return true; } }); /** * Inject user ID helper script into a specific tab */ async function injectUserIdHelper(tabId?: number): Promise<{ success: boolean; message: string }> { try { let targetTabId = tabId; // If no tab ID provided, use the active tab if (!targetTabId) { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) { throw new Error('No active tab found'); } targetTabId = tabs[0].id; } // Inject the user ID helper script await chrome.scripting.executeScript({ target: { tabId: targetTabId }, files: ['inject-scripts/user-id-helper.js'], }); // Get current user ID and inject it if (remoteServerClient) { const userId = await remoteServerClient.getCurrentUserId(); if (userId) { // Inject the user ID into the page await chrome.scripting.executeScript({ target: { tabId: targetTabId }, func: (userId) => { // Make user ID available globally (window as any).chromeExtensionUserId = userId; // Store in sessionStorage try { sessionStorage.setItem('chromeExtensionUserId', userId); } catch (e) { // Ignore storage errors } // Dispatch event for pages waiting for user ID window.dispatchEvent( new CustomEvent('chromeExtensionUserIdReady', { detail: { userId: userId }, }), ); console.log('Chrome Extension User ID injected:', userId); }, args: [userId], }); return { success: true, message: `User ID helper injected into tab ${targetTabId} with user ID: ${userId}`, }; } else { return { success: true, message: `User ID helper injected into tab ${targetTabId} but no user ID available (not connected)`, }; } } else { return { success: true, message: `User ID helper injected into tab ${targetTabId} but remote server client not initialized`, }; } } catch (error) { console.error('Failed to inject user ID helper:', error); throw error; } }