From e7d38c60236b765339e0b6f5f688057e234b899a Mon Sep 17 00:00:00 2001 From: Zane <75694352+zanesq@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:20:10 -0700 Subject: [PATCH] Disable updater until we can debug more in release (#2908) --- .../settings/app/AppSettingsSection.tsx | 23 +- ui/desktop/src/main.ts | 63 ++- ui/desktop/src/preload.ts | 26 ++ ui/desktop/src/updates.ts | 2 +- ui/desktop/src/utils/autoUpdater.ts | 401 +++++++++++------- ui/desktop/src/utils/githubUpdater.ts | 31 ++ 6 files changed, 388 insertions(+), 158 deletions(-) diff --git a/ui/desktop/src/components/settings/app/AppSettingsSection.tsx b/ui/desktop/src/components/settings/app/AppSettingsSection.tsx index a586fd71..b798a802 100644 --- a/ui/desktop/src/components/settings/app/AppSettingsSection.tsx +++ b/ui/desktop/src/components/settings/app/AppSettingsSection.tsx @@ -1,7 +1,6 @@ import { useState, useEffect, useRef } from 'react'; import { Switch } from '../../ui/switch'; import UpdateSection from './UpdateSection'; -import { UPDATES_ENABLED } from '../../../updates'; interface AppSettingsSectionProps { scrollToSection?: string; @@ -12,6 +11,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti const [dockIconEnabled, setDockIconEnabled] = useState(true); const [isMacOS, setIsMacOS] = useState(false); const [isDockSwitchDisabled, setIsDockSwitchDisabled] = useState(false); + const [updatesEnabled, setUpdatesEnabled] = useState(false); const updateSectionRef = useRef(null); // Check if running on macOS @@ -19,6 +19,25 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti setIsMacOS(window.electron.platform === 'darwin'); }, []); + // Load updater state + useEffect(() => { + window.electron.getUpdaterEnabled().then((enabled) => { + setUpdatesEnabled(enabled); + }); + + // Listen for updater state changes + const handleUpdaterStateChange = (enabled: boolean) => { + setUpdatesEnabled(enabled); + }; + + window.electron.onUpdaterStateChanged(handleUpdaterStateChange); + + // Cleanup listener on unmount + return () => { + window.electron.removeUpdaterStateListener(handleUpdaterStateChange); + }; + }, []); + // Handle scrolling to update section useEffect(() => { if (scrollToSection === 'update' && updateSectionRef.current) { @@ -125,7 +144,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti {/* Update Section */} - {UPDATES_ENABLED && ( + {updatesEnabled && (
diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 64be6e50..9a50cf28 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -37,12 +37,31 @@ import * as yaml from 'yaml'; import windowStateKeeper from 'electron-window-state'; import { setupAutoUpdater, + registerUpdateIpcHandlers, setTrayRef, updateTrayMenu, getUpdateAvailable, } from './utils/autoUpdater'; import { UPDATES_ENABLED } from './updates'; +// Updater toggle functions (moved here to keep updates.ts minimal for release replacement) +let updatesEnabled = UPDATES_ENABLED; + +function toggleUpdates(): boolean { + updatesEnabled = !updatesEnabled; + return updatesEnabled; +} + +function getUpdatesEnabled(): boolean { + // Only return the toggle state, ignore ENABLE_DEV_UPDATES for UI visibility + return updatesEnabled; +} + +function shouldSetupUpdater(): boolean { + // Setup updater if either the toggle is enabled OR dev updates are enabled + return updatesEnabled || process.env.ENABLE_DEV_UPDATES === 'true'; +} + // Define temp directory for pasted images const gooseTempDir = path.join(app.getPath('temp'), 'goose-pasted-images'); @@ -1157,8 +1176,11 @@ const registerGlobalHotkey = (accelerator: string) => { }; app.whenReady().then(async () => { - // Setup auto-updater - UPDATES_ENABLED && setupAutoUpdater(); + // Register update IPC handlers once + registerUpdateIpcHandlers(); + + // Setup auto-updater if enabled + shouldSetupUpdater() && setupAutoUpdater(); // Add CSP headers to all sessions session.defaultSession.webRequest.onHeadersReceived((details, callback) => { @@ -1200,6 +1222,38 @@ app.whenReady().then(async () => { // Register the default global hotkey registerGlobalHotkey('CommandOrControl+Alt+Shift+G'); + // Register hidden key combination to toggle updater (Cmd+Shift+U+P+D+A+T+E) + globalShortcut.register('CommandOrControl+Shift+U', () => { + // This is a multi-key sequence, we'll use a simpler approach + // Register a hidden key combination: Cmd/Ctrl + Alt + Shift + U for "Update toggle" + const newState = toggleUpdates(); + log.info( + `Updater toggled via keyboard shortcut. New state: ${newState ? 'ENABLED' : 'DISABLED'}` + ); + + // Show a notification to the user + new Notification({ + title: 'Goose Updater', + body: `Updates ${newState ? 'enabled' : 'disabled'}`, + }).show(); + + // If we're enabling updates and haven't set up the auto-updater yet, set it up now + if (newState) { + try { + setupAutoUpdater(tray || undefined); + log.info('Auto-updater setup completed after keyboard toggle'); + } catch (error) { + log.error('Error setting up auto-updater after keyboard toggle:', error); + } + } + + // Notify all windows about the updater state change + const windows = BrowserWindow.getAllWindows(); + windows.forEach((win) => { + win.webContents.send('updater-state-changed', newState); + }); + }); + session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => { details.requestHeaders['Origin'] = 'http://localhost:5173'; callback({ cancel: false, requestHeaders: details.requestHeaders }); @@ -1610,6 +1664,11 @@ app.whenReady().then(async () => { ipcMain.on('get-app-version', (event) => { event.returnValue = app.getVersion(); }); + + // Handler for getting updater state + ipcMain.handle('get-updater-enabled', () => { + return getUpdatesEnabled(); + }); }); /** diff --git a/ui/desktop/src/preload.ts b/ui/desktop/src/preload.ts index d79f68a5..731a9d00 100644 --- a/ui/desktop/src/preload.ts +++ b/ui/desktop/src/preload.ts @@ -89,6 +89,10 @@ type ElectronAPI = { restartApp: () => void; onUpdaterEvent: (callback: (event: UpdaterEvent) => void) => void; getUpdateState: () => Promise<{ updateAvailable: boolean; latestVersion?: string } | null>; + // Updater state functions + getUpdaterEnabled: () => Promise; + onUpdaterStateChanged: (callback: (enabled: boolean) => void) => void; + removeUpdaterStateListener: (callback: (enabled: boolean) => void) => void; }; type AppConfigAPI = { @@ -96,6 +100,12 @@ type AppConfigAPI = { getAll: () => Record; }; +// Store callback wrappers for proper cleanup +const updaterStateCallbacks = new Map< + (enabled: boolean) => void, + (event: Electron.IpcRendererEvent, enabled: boolean) => void +>(); + const electronAPI: ElectronAPI = { platform: process.platform, reactReady: () => ipcRenderer.send('react-ready'), @@ -183,6 +193,22 @@ const electronAPI: ElectronAPI = { getUpdateState: (): Promise<{ updateAvailable: boolean; latestVersion?: string } | null> => { return ipcRenderer.invoke('get-update-state'); }, + // Updater state functions + getUpdaterEnabled: (): Promise => { + return ipcRenderer.invoke('get-updater-enabled'); + }, + onUpdaterStateChanged: (callback: (enabled: boolean) => void): void => { + const wrapper = (_event: Electron.IpcRendererEvent, enabled: boolean) => callback(enabled); + updaterStateCallbacks.set(callback, wrapper); + ipcRenderer.on('updater-state-changed', wrapper); + }, + removeUpdaterStateListener: (callback: (enabled: boolean) => void): void => { + const wrapper = updaterStateCallbacks.get(callback); + if (wrapper) { + ipcRenderer.off('updater-state-changed', wrapper); + updaterStateCallbacks.delete(callback); + } + }, }; const appConfigAPI: AppConfigAPI = { diff --git a/ui/desktop/src/updates.ts b/ui/desktop/src/updates.ts index da6e19cf..1ba31dab 100644 --- a/ui/desktop/src/updates.ts +++ b/ui/desktop/src/updates.ts @@ -1 +1 @@ -export const UPDATES_ENABLED = true; +export const UPDATES_ENABLED = false; diff --git a/ui/desktop/src/utils/autoUpdater.ts b/ui/desktop/src/utils/autoUpdater.ts index d61922bf..524c112e 100644 --- a/ui/desktop/src/utils/autoUpdater.ts +++ b/ui/desktop/src/utils/autoUpdater.ts @@ -30,189 +30,68 @@ let githubUpdateInfo: { // Store update state let lastUpdateState: { updateAvailable: boolean; latestVersion?: string } | null = null; -// Configure auto-updater -export function setupAutoUpdater(tray?: Tray) { - if (tray) { - trayRef = tray; +// Track if IPC handlers have been registered +let ipcUpdateHandlersRegistered = false; + +// Register IPC handlers (only once) +export function registerUpdateIpcHandlers() { + if (ipcUpdateHandlersRegistered) { + return; } - // Set the feed URL for GitHub releases - autoUpdater.setFeedURL({ - provider: 'github', - owner: 'block', - repo: 'goose', - releaseType: 'release', - }); - - // Configure auto-updater settings - autoUpdater.autoDownload = false; // We'll trigger downloads manually - autoUpdater.autoInstallOnAppQuit = true; - - // Enable updates in development mode for testing - if (process.env.ENABLE_DEV_UPDATES === 'true') { - autoUpdater.forceDevUpdateConfig = true; - } - - // Set logger - autoUpdater.logger = log; - - // Check for updates on startup - setTimeout(() => { - log.info('Checking for updates on startup...'); - autoUpdater.checkForUpdates().catch((err) => { - log.error('Error checking for updates on startup:', err); - // If electron-updater fails, try GitHub API as fallback - if ( - err.message.includes('HttpError: 404') || - err.message.includes('ERR_CONNECTION_REFUSED') || - err.message.includes('ENOTFOUND') - ) { - log.info('Using GitHub API fallback for startup update check...'); - isUsingGitHubFallback = true; - - githubUpdater - .checkForUpdates() - .then((result) => { - if (result.error) { - sendStatusToWindow('error', result.error); - } else if (result.updateAvailable) { - // Store GitHub update info - githubUpdateInfo = { - latestVersion: result.latestVersion, - downloadUrl: result.downloadUrl, - releaseUrl: result.releaseUrl, - }; - - updateAvailable = true; - lastUpdateState = { updateAvailable: true, latestVersion: result.latestVersion }; - updateTrayIcon(true); - sendStatusToWindow('update-available', { version: result.latestVersion }); - } else { - updateAvailable = false; - lastUpdateState = { updateAvailable: false }; - updateTrayIcon(false); - sendStatusToWindow('update-not-available', { - version: autoUpdater.currentVersion.version, - }); - } - }) - .catch((fallbackError) => { - log.error('GitHub fallback also failed on startup:', fallbackError); - }); - } - }); - }, 5000); // Wait 5 seconds after app starts - - // Handle update events - autoUpdater.on('checking-for-update', () => { - log.info('Checking for update...'); - sendStatusToWindow('checking-for-update'); - }); - - autoUpdater.on('update-available', (info: UpdateInfo) => { - log.info('Update available:', info); - updateAvailable = true; - lastUpdateState = { updateAvailable: true, latestVersion: info.version }; - updateTrayIcon(true); - sendStatusToWindow('update-available', info); - }); - - autoUpdater.on('update-not-available', (info: UpdateInfo) => { - log.info('Update not available:', info); - updateAvailable = false; - lastUpdateState = { updateAvailable: false }; - updateTrayIcon(false); - sendStatusToWindow('update-not-available', info); - }); - - autoUpdater.on('error', async (err) => { - log.error('Error in auto-updater:', err); - - // Check if this is a 404 error (missing update files) or connection error - if ( - err.message.includes('HttpError: 404') || - err.message.includes('ERR_CONNECTION_REFUSED') || - err.message.includes('ENOTFOUND') - ) { - log.info('Falling back to GitHub API for update check...'); - isUsingGitHubFallback = true; - - try { - const result = await githubUpdater.checkForUpdates(); - - if (result.error) { - sendStatusToWindow('error', result.error); - } else if (result.updateAvailable) { - // Store GitHub update info - githubUpdateInfo = { - latestVersion: result.latestVersion, - downloadUrl: result.downloadUrl, - releaseUrl: result.releaseUrl, - }; - - updateAvailable = true; - updateTrayIcon(true); - sendStatusToWindow('update-available', { version: result.latestVersion }); - } else { - updateAvailable = false; - updateTrayIcon(false); - sendStatusToWindow('update-not-available', { - version: autoUpdater.currentVersion.version, - }); - } - } catch (fallbackError) { - log.error('GitHub fallback also failed:', fallbackError); - sendStatusToWindow( - 'error', - 'Unable to check for updates. Please check your internet connection.' - ); - } - } else { - sendStatusToWindow('error', err.message); - } - }); - - autoUpdater.on('download-progress', (progressObj) => { - let log_message = 'Download speed: ' + progressObj.bytesPerSecond; - log_message = log_message + ' - Downloaded ' + progressObj.percent + '%'; - log_message = log_message + ' (' + progressObj.transferred + '/' + progressObj.total + ')'; - log.info(log_message); - sendStatusToWindow('download-progress', progressObj); - }); - - autoUpdater.on('update-downloaded', (info: UpdateInfo) => { - log.info('Update downloaded:', info); - sendStatusToWindow('update-downloaded', info); - }); + log.info('Registering update IPC handlers...'); + ipcUpdateHandlersRegistered = true; // IPC handlers for renderer process ipcMain.handle('check-for-updates', async () => { try { + log.info('Manual check for updates requested'); + // Reset fallback flag isUsingGitHubFallback = false; githubUpdateInfo = {}; // Ensure auto-updater is properly initialized if (!autoUpdater.currentVersion) { + log.error('Auto-updater currentVersion is null/undefined'); throw new Error('Auto-updater not initialized. Please restart the application.'); } + log.info( + `About to check for updates with currentVersion: ${JSON.stringify(autoUpdater.currentVersion)}` + ); + log.info(`Feed URL: ${autoUpdater.getFeedURL()}`); + const result = await autoUpdater.checkForUpdates(); + log.info('Auto-updater checkForUpdates result:', result); + return { updateInfo: result?.updateInfo, error: null, }; } catch (error) { log.error('Error checking for updates:', error); + log.error('Manual check error details:', { + message: error instanceof Error ? error.message : 'Unknown error', + stack: error instanceof Error ? error.stack : 'No stack', + name: error instanceof Error ? error.name : 'Unknown', + code: + error instanceof Error && 'code' in error + ? (error as Error & { code: unknown }).code + : undefined, + toString: error?.toString(), + }); // If electron-updater fails, try GitHub API fallback if ( error instanceof Error && (error.message.includes('HttpError: 404') || error.message.includes('ERR_CONNECTION_REFUSED') || - error.message.includes('ENOTFOUND')) + error.message.includes('ENOTFOUND') || + error.message.includes('No published versions')) ) { log.info('Using GitHub API fallback in check-for-updates...'); + log.info('Manual fallback triggered by error:', error.message); isUsingGitHubFallback = true; try { @@ -365,6 +244,222 @@ export function setupAutoUpdater(tray?: Tray) { }); } +// Configure auto-updater +export function setupAutoUpdater(tray?: Tray) { + if (tray) { + trayRef = tray; + } + + log.info('Setting up auto-updater...'); + log.info(`Current app version: ${app.getVersion()}`); + log.info(`Platform: ${process.platform}, Arch: ${process.arch}`); + log.info(`NODE_ENV: ${process.env.NODE_ENV}`); + log.info(`ENABLE_DEV_UPDATES: ${process.env.ENABLE_DEV_UPDATES}`); + log.info(`App is packaged: ${app.isPackaged}`); + log.info(`App path: ${app.getAppPath()}`); + log.info(`Resources path: ${process.resourcesPath}`); + + // Set the feed URL for GitHub releases + const feedConfig = { + provider: 'github' as const, + owner: 'block', + repo: 'goose', + releaseType: 'release' as const, + }; + + log.info('Setting feed URL with config:', feedConfig); + autoUpdater.setFeedURL(feedConfig); + + // Log the feed URL after setting it + try { + const feedUrl = autoUpdater.getFeedURL(); + log.info(`Feed URL set to: ${feedUrl}`); + } catch (e) { + log.error('Error getting feed URL:', e); + } + + // Configure auto-updater settings + autoUpdater.autoDownload = false; // We'll trigger downloads manually + autoUpdater.autoInstallOnAppQuit = true; + + // Enable updates in development mode for testing + if (process.env.ENABLE_DEV_UPDATES === 'true') { + log.info('Enabling dev updates config'); + autoUpdater.forceDevUpdateConfig = true; + } + + // Additional debugging for release builds + if (app.isPackaged) { + log.info('App is packaged - this is a release build'); + // Try to get more info about the updater configuration + try { + log.info(`Auto-updater channel: ${autoUpdater.channel}`); + log.info(`Auto-updater allowPrerelease: ${autoUpdater.allowPrerelease}`); + log.info(`Auto-updater allowDowngrade: ${autoUpdater.allowDowngrade}`); + } catch (e) { + log.error('Error getting auto-updater properties:', e); + } + } else { + log.info('App is not packaged - this is a development build'); + } + + // Set logger + autoUpdater.logger = log; + + log.info('Auto-updater setup completed'); + + // Check for updates on startup + setTimeout(() => { + log.info('Checking for updates on startup...'); + log.info(`autoUpdater.currentVersion: ${JSON.stringify(autoUpdater.currentVersion)}`); + log.info(`autoUpdater.getFeedURL(): ${autoUpdater.getFeedURL()}`); + + autoUpdater.checkForUpdates().catch((err) => { + log.error('Error checking for updates on startup:', err); + log.error('Error details:', { + message: err.message, + stack: err.stack, + name: err.name, + code: 'code' in err ? err.code : undefined, + }); + + // If electron-updater fails, try GitHub API as fallback + if ( + err.message.includes('HttpError: 404') || + err.message.includes('ERR_CONNECTION_REFUSED') || + err.message.includes('ENOTFOUND') || + err.message.includes('No published versions') + ) { + log.info('Using GitHub API fallback for startup update check...'); + log.info('Fallback triggered by error containing:', err.message); + isUsingGitHubFallback = true; + + githubUpdater + .checkForUpdates() + .then((result) => { + if (result.error) { + sendStatusToWindow('error', result.error); + } else if (result.updateAvailable) { + // Store GitHub update info + githubUpdateInfo = { + latestVersion: result.latestVersion, + downloadUrl: result.downloadUrl, + releaseUrl: result.releaseUrl, + }; + + updateAvailable = true; + lastUpdateState = { updateAvailable: true, latestVersion: result.latestVersion }; + updateTrayIcon(true); + sendStatusToWindow('update-available', { version: result.latestVersion }); + } else { + updateAvailable = false; + lastUpdateState = { updateAvailable: false }; + updateTrayIcon(false); + sendStatusToWindow('update-not-available', { + version: autoUpdater.currentVersion.version, + }); + } + }) + .catch((fallbackError) => { + log.error('GitHub fallback also failed on startup:', fallbackError); + }); + } + }); + }, 5000); // Wait 5 seconds after app starts + + // Handle update events + autoUpdater.on('checking-for-update', () => { + log.info('Auto-updater: Checking for update...'); + log.info(`Auto-updater: Feed URL during check: ${autoUpdater.getFeedURL()}`); + sendStatusToWindow('checking-for-update'); + }); + + autoUpdater.on('update-available', (info: UpdateInfo) => { + log.info('Update available:', info); + updateAvailable = true; + lastUpdateState = { updateAvailable: true, latestVersion: info.version }; + updateTrayIcon(true); + sendStatusToWindow('update-available', info); + }); + + autoUpdater.on('update-not-available', (info: UpdateInfo) => { + log.info('Update not available:', info); + updateAvailable = false; + lastUpdateState = { updateAvailable: false }; + updateTrayIcon(false); + sendStatusToWindow('update-not-available', info); + }); + + autoUpdater.on('error', async (err) => { + log.error('Error in auto-updater:', err); + log.error('Auto-updater error details:', { + message: err.message, + stack: err.stack, + name: err.name, + code: 'code' in err ? err.code : undefined, + toString: err.toString(), + }); + + // Check if this is a 404 error (missing update files) or connection error + if ( + err.message.includes('HttpError: 404') || + err.message.includes('ERR_CONNECTION_REFUSED') || + err.message.includes('ENOTFOUND') || + err.message.includes('No published versions') + ) { + log.info('Falling back to GitHub API for update check...'); + log.info('Fallback triggered by error:', err.message); + isUsingGitHubFallback = true; + + try { + const result = await githubUpdater.checkForUpdates(); + + if (result.error) { + sendStatusToWindow('error', result.error); + } else if (result.updateAvailable) { + // Store GitHub update info + githubUpdateInfo = { + latestVersion: result.latestVersion, + downloadUrl: result.downloadUrl, + releaseUrl: result.releaseUrl, + }; + + updateAvailable = true; + updateTrayIcon(true); + sendStatusToWindow('update-available', { version: result.latestVersion }); + } else { + updateAvailable = false; + updateTrayIcon(false); + sendStatusToWindow('update-not-available', { + version: autoUpdater.currentVersion.version, + }); + } + } catch (fallbackError) { + log.error('GitHub fallback also failed:', fallbackError); + sendStatusToWindow( + 'error', + 'Unable to check for updates. Please check your internet connection.' + ); + } + } else { + sendStatusToWindow('error', err.message); + } + }); + + autoUpdater.on('download-progress', (progressObj) => { + let log_message = 'Download speed: ' + progressObj.bytesPerSecond; + log_message = log_message + ' - Downloaded ' + progressObj.percent + '%'; + log_message = log_message + ' (' + progressObj.transferred + '/' + progressObj.total + ')'; + log.info(log_message); + sendStatusToWindow('download-progress', progressObj); + }); + + autoUpdater.on('update-downloaded', (info: UpdateInfo) => { + log.info('Update downloaded:', info); + sendStatusToWindow('update-downloaded', info); + }); +} + interface UpdaterEvent { event: string; data?: unknown; diff --git a/ui/desktop/src/utils/githubUpdater.ts b/ui/desktop/src/utils/githubUpdater.ts index c6d4dd4f..28dbaf3e 100644 --- a/ui/desktop/src/utils/githubUpdater.ts +++ b/ui/desktop/src/utils/githubUpdater.ts @@ -34,6 +34,8 @@ export class GitHubUpdater { async checkForUpdates(): Promise { try { log.info('GitHubUpdater: Checking for updates via GitHub API...'); + log.info(`GitHubUpdater: API URL: ${this.apiUrl}`); + log.info(`GitHubUpdater: Current app version: ${app.getVersion()}`); const response = await fetch(this.apiUrl, { headers: { @@ -42,11 +44,21 @@ export class GitHubUpdater { }, }); + log.info( + `GitHubUpdater: GitHub API response status: ${response.status} ${response.statusText}` + ); + if (!response.ok) { + const errorText = await response.text(); + log.error(`GitHubUpdater: GitHub API error response: ${errorText}`); throw new Error(`GitHub API returned ${response.status}: ${response.statusText}`); } const release: GitHubRelease = await response.json(); + log.info(`GitHubUpdater: Found release: ${release.tag_name} (${release.name})`); + log.info(`GitHubUpdater: Release published at: ${release.published_at}`); + log.info(`GitHubUpdater: Release assets count: ${release.assets.length}`); + const latestVersion = release.tag_name.replace(/^v/, ''); // Remove 'v' prefix if present const currentVersion = app.getVersion(); @@ -56,6 +68,7 @@ export class GitHubUpdater { // Compare versions const updateAvailable = compareVersions(latestVersion, currentVersion) > 0; + log.info(`GitHubUpdater: Update available: ${updateAvailable}`); if (!updateAvailable) { return { @@ -70,6 +83,8 @@ export class GitHubUpdater { let downloadUrl: string | undefined; let assetName: string; + log.info(`GitHubUpdater: Looking for asset for platform: ${platform}, arch: ${arch}`); + if (platform === 'darwin') { // macOS if (arch === 'arm64') { @@ -85,9 +100,16 @@ export class GitHubUpdater { assetName = `Goose-linux-${arch}.zip`; } + log.info(`GitHubUpdater: Looking for asset named: ${assetName}`); + log.info(`GitHubUpdater: Available assets: ${release.assets.map((a) => a.name).join(', ')}`); + const asset = release.assets.find((a) => a.name === assetName); if (asset) { downloadUrl = asset.browser_download_url; + log.info(`GitHubUpdater: Found matching asset: ${asset.name} (${asset.size} bytes)`); + log.info(`GitHubUpdater: Download URL: ${downloadUrl}`); + } else { + log.warn(`GitHubUpdater: No matching asset found for ${assetName}`); } return { @@ -98,6 +120,15 @@ export class GitHubUpdater { }; } catch (error) { log.error('GitHubUpdater: Error checking for updates:', error); + log.error('GitHubUpdater: Error details:', { + message: error instanceof Error ? error.message : 'Unknown error', + stack: error instanceof Error ? error.stack : 'No stack', + name: error instanceof Error ? error.name : 'Unknown', + code: + error instanceof Error && 'code' in error + ? (error as Error & { code: unknown }).code + : undefined, + }); return { updateAvailable: false, error: error instanceof Error ? error.message : 'Unknown error',