From 15f6973bcfdc63cc15495236d51f3481f698e129 Mon Sep 17 00:00:00 2001 From: Lily Delalande <119957291+lily-de@users.noreply.github.com> Date: Wed, 19 Mar 2025 14:55:11 -0400 Subject: [PATCH] ui: add logs to app (#1760) --- ui/desktop/openapi.json | 2 +- ui/desktop/src/App.tsx | 199 ++++++++++++++++++++++++++++++---------- 2 files changed, 152 insertions(+), 49 deletions(-) diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index f0f203b9..587a6981 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -10,7 +10,7 @@ "license": { "name": "Apache-2.0" }, - "version": "1.0.14" + "version": "1.0.15" }, "paths": { "/config": { diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 1f63e9b2..f9d909a7 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -73,62 +73,107 @@ export default function App() { return `${cmd} ${args.join(' ')}`.trim(); } + // this is all settings v2 stuff useEffect(() => { // Skip if feature flag is not enabled if (!process.env.ALPHA) { return; } + console.log('Alpha flow initializing...'); + const setupExtensions = async () => { try { + console.log('Setting up extensions...'); + // Set the ref immediately to prevent duplicate runs initAttemptedRef.current = true; + console.log('Set initAttemptedRef to prevent duplicate runs'); // Force refresh extensions from the backend to ensure we have the latest + console.log('Getting extensions from backend...'); const refreshedExtensions = await getExtensions(true); + console.log(`Retrieved ${refreshedExtensions.length} extensions`); if (refreshedExtensions.length === 0) { // If we still have no extensions, this is truly a first-time setup console.log('First-time setup: Adding all built-in extensions...'); await initializeBuiltInExtensions(addExtension); + console.log('Built-in extensions initialization complete'); } else { // Extensions exist, check for any missing built-ins console.log('Checking for missing built-in extensions...'); - console.log(refreshedExtensions); + console.log('Current extensions:', refreshedExtensions); await syncBuiltInExtensions(refreshedExtensions, addExtension); + console.log('Built-in extensions sync complete'); } } catch (error) { console.error('Error setting up extensions:', error); + console.error('Extension setup error details:', { + message: error.message, + stack: error.stack, + name: error.name, + }); + // We don't set fatal error here since the app might still work without extensions } }; const initializeApp = async () => { try { + console.log('Initializing alpha app...'); + // Check if we have the required configuration + console.log('Reading GOOSE_PROVIDER from config...'); const provider = (await read('GOOSE_PROVIDER', false)) as string; + console.log('Provider from config:', provider); + + console.log('Reading GOOSE_MODEL from config...'); const model = (await read('GOOSE_MODEL', false)) as string; + console.log('Model from config:', model); if (provider && model) { // We have all needed configuration, initialize the system - console.log('Initializing system with stored GOOSE_MODEL and GOOSE_PROVIDER'); + console.log(`Initializing system with provider: ${provider}, model: ${model}`); await initializeSystem(provider, model); + console.log('System initialization successful'); setView('chat'); } else { // Missing configuration, show onboarding console.log('Missing configuration, showing onboarding'); + if (!provider) console.log('Missing provider'); + if (!model) console.log('Missing model'); setView('welcome'); } } catch (error) { console.error('Error initializing app:', error); + console.error('App initialization error details:', { + message: error.message, + stack: error.stack, + name: error.name, + }); + setFatalError(`Alpha initialization error: ${error.message || 'Unknown error'}`); setView('welcome'); } }; - initializeApp().then(); - setupExtensions().then(); + // Execute with better promise handling + initializeApp() + .then(() => console.log('Alpha app initialization complete')) + .catch((error) => { + console.error('Unhandled error in initializeApp:', error); + setFatalError(`Unhandled alpha app error: ${error.message || 'Unknown error'}`); + }); + + setupExtensions() + .then(() => console.log('Extensions setup complete')) + .catch((error) => { + console.error('Unhandled error in setupExtensions:', error); + // Not setting fatal error here since extensions are optional + }); }, []); // Empty dependency array since we're using initAttemptedRef const setView = (view: View, viewOptions: Record = {}) => { + console.log(`Setting view to: ${view}`, viewOptions); setInternalView({ view, viewOptions }); }; @@ -136,14 +181,29 @@ export default function App() { const [isLoadingSession, setIsLoadingSession] = useState(false); const { chat, setChat } = useChat({ setView, setIsLoadingSession }); - useEffect(() => window.electron.reactReady(), []); + useEffect(() => { + console.log('Sending reactReady signal to Electron'); + try { + window.electron.reactReady(); + } catch (error) { + console.error('Error sending reactReady:', error); + setFatalError(`React ready notification failed: ${error.message}`); + } + }, []); // Keyboard shortcut handler useEffect(() => { + console.log('Setting up keyboard shortcuts'); const handleKeyDown = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key === 'n') { event.preventDefault(); - window.electron.createChatWindow(undefined, window.appConfig.get('GOOSE_WORKING_DIR')); + try { + const workingDir = window.appConfig.get('GOOSE_WORKING_DIR'); + console.log(`Creating new chat window with working dir: ${workingDir}`); + window.electron.createChatWindow(undefined, workingDir); + } catch (error) { + console.error('Error creating new window:', error); + } } }; @@ -154,7 +214,12 @@ export default function App() { }, []); useEffect(() => { + console.log('Setting up fatal error handler'); const handleFatalError = (_: any, errorMessage: string) => { + console.error('Encountered a fatal error: ', errorMessage); + // Log additional context that might help diagnose the issue + console.error('Current view:', view); + console.error('Is loading session:', isLoadingSession); setFatalError(errorMessage); }; @@ -162,32 +227,45 @@ export default function App() { return () => { window.electron.off('fatal-error', handleFatalError); }; - }, []); + }, [view, isLoadingSession]); // Add dependencies to provide context in error logs useEffect(() => { - const handleSetView = (_, view) => setView(view); + console.log('Setting up view change handler'); + const handleSetView = (_, newView) => { + console.log(`Received view change request to: ${newView}`); + setView(newView); + }; + window.electron.on('set-view', handleSetView); return () => window.electron.off('set-view', handleSetView); }, []); // Add cleanup for session states when view changes useEffect(() => { + console.log(`View changed to: ${view}`); if (view !== 'chat') { + console.log('Not in chat view, clearing loading session state'); setIsLoadingSession(false); } }, [view]); // TODO: modify useEffect(() => { + console.log('Setting up extension handler'); const handleAddExtension = (_: any, link: string) => { - const command = extractCommand(link); - const extName = extractExtensionName(link); - window.electron.logInfo(`Adding extension from deep link ${link}`); - setPendingLink(link); - setModalMessage( - `Are you sure you want to install the ${extName} extension?\n\nCommand: ${command}` - ); - setModalVisible(true); + try { + console.log(`Received add-extension event with link: ${link}`); + const command = extractCommand(link); + const extName = extractExtensionName(link); + window.electron.logInfo(`Adding extension from deep link ${link}`); + setPendingLink(link); + setModalMessage( + `Are you sure you want to install the ${extName} extension?\n\nCommand: ${command}` + ); + setModalVisible(true); + } catch (error) { + console.error('Error handling add-extension event:', error); + } }; window.electron.on('add-extension', handleAddExtension); @@ -199,11 +277,14 @@ export default function App() { // TODO: modify const handleConfirm = async () => { if (pendingLink && !isInstalling) { + console.log(`Confirming installation of extension from: ${pendingLink}`); setIsInstalling(true); try { await addExtensionFromDeepLink(pendingLink, setView); + console.log('Extension installation successful'); } catch (error) { console.error('Failed to add extension:', error); + // Consider showing a user-visible error notification here } finally { setModalVisible(false); setPendingLink(null); @@ -219,6 +300,7 @@ export default function App() { setPendingLink(null); }; + // TODO: remove const { switchModel } = useModel(); // TODO: remove const { addRecentModel } = useRecentModels(); // TODO: remove @@ -227,50 +309,71 @@ export default function App() { return; } - // TODO: remove + console.log('Non-alpha flow initializing...'); + // Attempt to detect config for a stored provider const detectStoredProvider = () => { - const config = window.electron.getConfig(); - const storedProvider = getStoredProvider(config); - if (storedProvider) { - setView('chat'); - } else { - setView('welcome'); + try { + const config = window.electron.getConfig(); + console.log('Loaded config:', JSON.stringify(config)); + + const storedProvider = getStoredProvider(config); + console.log('Stored provider:', storedProvider); + + if (storedProvider) { + setView('chat'); + } else { + setView('welcome'); + } + } catch (err) { + console.error('DETECTION ERROR:', err); + setFatalError(`Config detection error: ${err.message || 'Unknown error'}`); } }; - // TODO: remove // Initialize system if we have a stored provider const setupStoredProvider = async () => { - const config = window.electron.getConfig(); + try { + const config = window.electron.getConfig(); - if (config.GOOSE_PROVIDER && config.GOOSE_MODEL) { - window.electron.logInfo( - 'Initializing system with environment: GOOSE_MODEL and GOOSE_PROVIDER as priority.' - ); - await initializeSystem(config.GOOSE_PROVIDER, config.GOOSE_MODEL); - return; - } - const storedProvider = getStoredProvider(config); - const storedModel = getStoredModel(); - if (storedProvider) { - try { - await initializeSystem(storedProvider, storedModel); - - if (!storedModel) { - const modelName = getDefaultModel(storedProvider.toLowerCase()); - const model = createSelectedModel(storedProvider.toLowerCase(), modelName); - switchModel(model); - addRecentModel(model); - } - } catch (error) { - // TODO: add sessionError state and show error screen with option to start fresh - console.error('Failed to initialize with stored provider:', error); + if (config.GOOSE_PROVIDER && config.GOOSE_MODEL) { + console.log('using GOOSE_PROVIDER and GOOSE_MODEL from config'); + await initializeSystem(config.GOOSE_PROVIDER, config.GOOSE_MODEL); + return; } + + const storedProvider = getStoredProvider(config); + const storedModel = getStoredModel(); + + if (storedProvider) { + try { + await initializeSystem(storedProvider, storedModel); + console.log('Setup using locally stored provider:', storedProvider); + console.log('Setup using locally stored model:', storedModel); + + if (!storedModel) { + const modelName = getDefaultModel(storedProvider.toLowerCase()); + const model = createSelectedModel(storedProvider.toLowerCase(), modelName); + switchModel(model); + addRecentModel(model); + } + } catch (error) { + console.error('Failed to initialize with stored provider:', error); + setFatalError(`Initialization failed: ${error.message || 'Unknown error'}`); + } + } + } catch (err) { + console.error('SETUP ERROR:', err); + setFatalError(`Setup error: ${err.message || 'Unknown error'}`); } }; + + // Execute the functions with better error handling detectStoredProvider(); - setupStoredProvider(); + setupStoredProvider().catch((err) => { + console.error('ASYNC SETUP ERROR:', err); + setFatalError(`Async setup error: ${err.message || 'Unknown error'}`); + }); }, []); // keep