"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Preload script — runs in every BrowserWindow before the page loads. * Exposes a minimal, secure API via contextBridge so the renderer can * communicate with the main-process auto-updater without nodeIntegration. */ const electron_1 = require("electron"); const updaterAPI = { onStateChanged: (callback) => { const handler = (_event, state) => { callback(state); }; electron_1.ipcRenderer.on('updater:state-changed', handler); // Return unsubscribe function return () => { electron_1.ipcRenderer.removeListener('updater:state-changed', handler); }; }, applyUpdate: () => electron_1.ipcRenderer.invoke('updater:apply'), quitAndInstall: () => electron_1.ipcRenderer.invoke('updater:quit-and-install'), checkForUpdates: () => electron_1.ipcRenderer.invoke('updater:check-for-updates'), }; const dialogAPI = { showOpenDialog: () => electron_1.ipcRenderer.invoke('dialog:open-workspace'), }; const notificationAPI = { send: (options) => electron_1.ipcRenderer.invoke('notification:send', options), openSystemPreferences: () => electron_1.ipcRenderer.invoke('notification:open-system-preferences'), onClicked: (callback) => { const handler = (_event, payload) => { callback(payload); }; electron_1.ipcRenderer.on('notification:clicked', handler); return () => { electron_1.ipcRenderer.removeListener('notification:clicked', handler); }; }, }; const storageAPI = { getItems: () => electron_1.ipcRenderer.invoke('storage:get-items'), updateItems: (changes) => electron_1.ipcRenderer.invoke('storage:update-items', changes), onChanged: (callback) => { const handler = (_event, changes) => { callback(changes); }; electron_1.ipcRenderer.on('storage:changed', handler); return () => { electron_1.ipcRenderer.removeListener('storage:changed', handler); }; }, }; const logsAPI = { getElectronLogs: () => electron_1.ipcRenderer.invoke('logs:electron'), }; const extensionsAPI = { sendAuthorities: (authoritiesMap) => electron_1.ipcRenderer.invoke('extensions:send-authorities', authoritiesMap), }; const deepLinkAPI = { onDeepLink: (callback) => { const handler = (_event, url) => { callback(url); }; electron_1.ipcRenderer.on('deep-link', handler); return () => { electron_1.ipcRenderer.removeListener('deep-link', handler); }; }, getStoredDeepLink: () => electron_1.ipcRenderer.invoke('deep-link:get-stored'), // Provider API provider: { getActive: () => electron_1.ipcRenderer.invoke('provider:get-active'), getAll: () => electron_1.ipcRenderer.invoke('provider:get-all'), openSettings: () => electron_1.ipcRenderer.invoke('provider:open-settings'), onOpenSettings: (handler) => { electron_1.ipcRenderer.on('provider:open-settings', handler); return () => electron_1.ipcRenderer.removeListener('provider:open-settings', handler); }, }, }; const agentAPI = { updateActiveAgentCount: (count) => electron_1.ipcRenderer.invoke('agent:update-active-count', count), }; const electronNativeAPI = { getZoomLevel: () => electron_1.webFrame.getZoomFactor(), setTitleBarOverlay: (options) => electron_1.ipcRenderer.invoke('window:set-title-bar-overlay', options), minimize: () => electron_1.ipcRenderer.invoke('window:minimize'), maximize: () => electron_1.ipcRenderer.invoke('window:maximize'), unmaximize: () => electron_1.ipcRenderer.invoke('window:unmaximize'), isMaximized: () => electron_1.ipcRenderer.invoke('window:is-maximized'), close: () => electron_1.ipcRenderer.invoke('window:close'), toggleDevTools: () => electron_1.ipcRenderer.invoke('window:toggle-devtools'), zoomIn: () => { const current = electron_1.webFrame.getZoomLevel(); electron_1.webFrame.setZoomLevel(current + 0.5); }, zoomOut: () => { const current = electron_1.webFrame.getZoomLevel(); electron_1.webFrame.setZoomLevel(current - 0.5); }, resetZoom: () => { electron_1.webFrame.setZoomLevel(0); }, openExternal: (url) => electron_1.ipcRenderer.invoke('shell:open-external', url), }; electron_1.contextBridge.exposeInMainWorld('electronUpdater', updaterAPI); electron_1.contextBridge.exposeInMainWorld('dialog', dialogAPI); electron_1.contextBridge.exposeInMainWorld('nativeNotifications', notificationAPI); electron_1.contextBridge.exposeInMainWorld('nativeStorage', storageAPI); electron_1.contextBridge.exposeInMainWorld('logs', logsAPI); electron_1.contextBridge.exposeInMainWorld('extensions', extensionsAPI); electron_1.contextBridge.exposeInMainWorld('deepLink', deepLinkAPI); electron_1.contextBridge.exposeInMainWorld('agent', agentAPI); electron_1.contextBridge.exposeInMainWorld('electronNative', electronNativeAPI); // --------------------------------------------------------------------------- // Native In-UI AI Provider Switcher // --------------------------------------------------------------------------- async function fetchEndpoints() { try { const res = await fetch('http://127.0.0.1:48080/codex/list-endpoints'); const data = await res.json(); return data; } catch (e) { console.error('Failed to fetch endpoints:', e); return null; } } async function switchEndpoint(name) { try { const res = await fetch('http://127.0.0.1:48080/codex/switch-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }) }); const data = await res.json(); return data.success; } catch (e) { console.error('Failed to switch endpoint:', e); return false; } } function setupAiProviderSwitcher() { if (window.self !== window.top) return; if (document.getElementById('codex-ai-switcher-container')) return; setTimeout(async () => { const data = await fetchEndpoints(); if (!data || !data.endpoints || data.endpoints.length === 0) { console.log('[Codex] No endpoints found or proxy not running.'); return; } const container = document.createElement('div'); container.id = 'codex-ai-switcher-container'; container.style.cssText = ` position: fixed; top: 8px; right: 80px; z-index: 999999; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; user-select: none; `; const style = document.createElement('style'); style.textContent = ` #codex-ai-btn { background: rgba(30, 30, 35, 0.65); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 18px; padding: 6px 12px; color: rgba(255, 255, 255, 0.9); font-size: 12px; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 6px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } #codex-ai-btn:hover { background: rgba(40, 40, 45, 0.8); border-color: rgba(255, 255, 255, 0.25); transform: translateY(-1px); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25); } #codex-ai-btn:active { transform: translateY(0); } #codex-ai-indicator { width: 7px; height: 7px; border-radius: 50%; background: #10b981; box-shadow: 0 0 8px #10b981; display: inline-block; animation: codex-pulse 2s infinite; } @keyframes codex-pulse { 0% { opacity: 0.6; box-shadow: 0 0 4px #10b981; } 50% { opacity: 1; box-shadow: 0 0 10px #10b981; } 100% { opacity: 0.6; box-shadow: 0 0 4px #10b981; } } #codex-ai-dropdown { position: absolute; top: calc(100% + 8px); right: 0; background: rgba(24, 24, 28, 0.95); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 12px; min-width: 200px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4); padding: 6px; opacity: 0; transform: translateY(-10px) scale(0.95); pointer-events: none; transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); } #codex-ai-dropdown.open { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; } .codex-ai-item { padding: 8px 12px; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; color: rgba(255, 255, 255, 0.7); display: flex; align-items: center; justify-content: space-between; gap: 8px; } .codex-ai-item:hover { background: rgba(255, 255, 255, 0.08); color: #fff; } .codex-ai-item.active { background: linear-gradient(135deg, rgba(99, 102, 241, 0.2), rgba(79, 70, 229, 0.25)); border: 1px solid rgba(99, 102, 241, 0.3); color: #818cf8; } .codex-ai-item.active:hover { background: linear-gradient(135deg, rgba(99, 102, 241, 0.3), rgba(79, 70, 229, 0.35)); } #codex-ai-toast { position: fixed; bottom: 24px; right: 24px; background: rgba(20, 20, 25, 0.85); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; padding: 10px 18px; color: #fff; font-size: 13px; font-weight: 500; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); display: flex; align-items: center; gap: 8px; transform: translateY(100px); opacity: 0; transition: all 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275); z-index: 1000000; } #codex-ai-toast.show { transform: translateY(0); opacity: 1; } #codex-ai-arrow { border: solid rgba(255, 255, 255, 0.6); border-width: 0 1.5px 1.5px 0; display: inline-block; padding: 2.5px; transform: rotate(45deg); margin-left: 2px; transition: transform 0.2s; } #codex-ai-btn.open-arrow #codex-ai-arrow { transform: rotate(-135deg); } `; document.head.appendChild(style); const btn = document.createElement('div'); btn.id = 'codex-ai-btn'; btn.innerHTML = `${data.active}`; const dropdown = document.createElement('div'); dropdown.id = 'codex-ai-dropdown'; const updateDropdownItems = (activeName) => { dropdown.innerHTML = ''; data.endpoints.forEach(ep => { const item = document.createElement('div'); item.className = 'codex-ai-item' + (ep.name === activeName ? ' active' : ''); item.innerHTML = ` ${ep.name} ${ep.backend_type} `; item.addEventListener('click', async (e) => { e.stopPropagation(); dropdown.classList.remove('open'); btn.classList.remove('open-arrow'); if (ep.name === activeName) return; const success = await switchEndpoint(ep.name); if (success) { activeName = ep.name; document.getElementById('codex-ai-btn-text').textContent = ep.name; updateDropdownItems(ep.name); showToast(`Switched provider to ${ep.name}`); } else { showToast('Failed to switch AI provider'); } }); dropdown.appendChild(item); }); }; updateDropdownItems(data.active); btn.addEventListener('click', (e) => { e.stopPropagation(); const isOpen = dropdown.classList.toggle('open'); btn.classList.toggle('open-arrow', isOpen); }); document.addEventListener('click', () => { dropdown.classList.remove('open'); btn.classList.remove('open-arrow'); }); container.appendChild(btn); container.appendChild(dropdown); document.body.appendChild(container); const toast = document.createElement('div'); toast.id = 'codex-ai-toast'; document.body.appendChild(toast); let toastTimeout = null; function showToast(message) { toast.textContent = message; toast.classList.add('show'); if (toastTimeout) clearTimeout(toastTimeout); toastTimeout = setTimeout(() => { toast.classList.remove('show'); }, 3000); } console.log('[Codex] Seamless AI provider switcher injected successfully.'); }, 1500); } window.addEventListener('DOMContentLoaded', () => { setupAiProviderSwitcher(); });