ui: add logs to app (#1760)

This commit is contained in:
Lily Delalande
2025-03-19 14:55:11 -04:00
committed by GitHub
parent d14e5f4de7
commit 15f6973bcf
2 changed files with 152 additions and 49 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
"license": { "license": {
"name": "Apache-2.0" "name": "Apache-2.0"
}, },
"version": "1.0.14" "version": "1.0.15"
}, },
"paths": { "paths": {
"/config": { "/config": {
+151 -48
View File
@@ -73,62 +73,107 @@ export default function App() {
return `${cmd} ${args.join(' ')}`.trim(); return `${cmd} ${args.join(' ')}`.trim();
} }
// this is all settings v2 stuff
useEffect(() => { useEffect(() => {
// Skip if feature flag is not enabled // Skip if feature flag is not enabled
if (!process.env.ALPHA) { if (!process.env.ALPHA) {
return; return;
} }
console.log('Alpha flow initializing...');
const setupExtensions = async () => { const setupExtensions = async () => {
try { try {
console.log('Setting up extensions...');
// Set the ref immediately to prevent duplicate runs // Set the ref immediately to prevent duplicate runs
initAttemptedRef.current = true; initAttemptedRef.current = true;
console.log('Set initAttemptedRef to prevent duplicate runs');
// Force refresh extensions from the backend to ensure we have the latest // Force refresh extensions from the backend to ensure we have the latest
console.log('Getting extensions from backend...');
const refreshedExtensions = await getExtensions(true); const refreshedExtensions = await getExtensions(true);
console.log(`Retrieved ${refreshedExtensions.length} extensions`);
if (refreshedExtensions.length === 0) { if (refreshedExtensions.length === 0) {
// If we still have no extensions, this is truly a first-time setup // If we still have no extensions, this is truly a first-time setup
console.log('First-time setup: Adding all built-in extensions...'); console.log('First-time setup: Adding all built-in extensions...');
await initializeBuiltInExtensions(addExtension); await initializeBuiltInExtensions(addExtension);
console.log('Built-in extensions initialization complete');
} else { } else {
// Extensions exist, check for any missing built-ins // Extensions exist, check for any missing built-ins
console.log('Checking for missing built-in extensions...'); console.log('Checking for missing built-in extensions...');
console.log(refreshedExtensions); console.log('Current extensions:', refreshedExtensions);
await syncBuiltInExtensions(refreshedExtensions, addExtension); await syncBuiltInExtensions(refreshedExtensions, addExtension);
console.log('Built-in extensions sync complete');
} }
} catch (error) { } catch (error) {
console.error('Error setting up extensions:', 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 () => { const initializeApp = async () => {
try { try {
console.log('Initializing alpha app...');
// Check if we have the required configuration // Check if we have the required configuration
console.log('Reading GOOSE_PROVIDER from config...');
const provider = (await read('GOOSE_PROVIDER', false)) as string; 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; const model = (await read('GOOSE_MODEL', false)) as string;
console.log('Model from config:', model);
if (provider && model) { if (provider && model) {
// We have all needed configuration, initialize the system // 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); await initializeSystem(provider, model);
console.log('System initialization successful');
setView('chat'); setView('chat');
} else { } else {
// Missing configuration, show onboarding // Missing configuration, show onboarding
console.log('Missing configuration, showing onboarding'); console.log('Missing configuration, showing onboarding');
if (!provider) console.log('Missing provider');
if (!model) console.log('Missing model');
setView('welcome'); setView('welcome');
} }
} catch (error) { } catch (error) {
console.error('Error initializing app:', 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'); setView('welcome');
} }
}; };
initializeApp().then(); // Execute with better promise handling
setupExtensions().then(); 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 }, []); // Empty dependency array since we're using initAttemptedRef
const setView = (view: View, viewOptions: Record<any, any> = {}) => { const setView = (view: View, viewOptions: Record<any, any> = {}) => {
console.log(`Setting view to: ${view}`, viewOptions);
setInternalView({ view, viewOptions }); setInternalView({ view, viewOptions });
}; };
@@ -136,14 +181,29 @@ export default function App() {
const [isLoadingSession, setIsLoadingSession] = useState(false); const [isLoadingSession, setIsLoadingSession] = useState(false);
const { chat, setChat } = useChat({ setView, setIsLoadingSession }); 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 // Keyboard shortcut handler
useEffect(() => { useEffect(() => {
console.log('Setting up keyboard shortcuts');
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
if ((event.metaKey || event.ctrlKey) && event.key === 'n') { if ((event.metaKey || event.ctrlKey) && event.key === 'n') {
event.preventDefault(); 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(() => { useEffect(() => {
console.log('Setting up fatal error handler');
const handleFatalError = (_: any, errorMessage: string) => { 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); setFatalError(errorMessage);
}; };
@@ -162,32 +227,45 @@ export default function App() {
return () => { return () => {
window.electron.off('fatal-error', handleFatalError); window.electron.off('fatal-error', handleFatalError);
}; };
}, []); }, [view, isLoadingSession]); // Add dependencies to provide context in error logs
useEffect(() => { 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); window.electron.on('set-view', handleSetView);
return () => window.electron.off('set-view', handleSetView); return () => window.electron.off('set-view', handleSetView);
}, []); }, []);
// Add cleanup for session states when view changes // Add cleanup for session states when view changes
useEffect(() => { useEffect(() => {
console.log(`View changed to: ${view}`);
if (view !== 'chat') { if (view !== 'chat') {
console.log('Not in chat view, clearing loading session state');
setIsLoadingSession(false); setIsLoadingSession(false);
} }
}, [view]); }, [view]);
// TODO: modify // TODO: modify
useEffect(() => { useEffect(() => {
console.log('Setting up extension handler');
const handleAddExtension = (_: any, link: string) => { const handleAddExtension = (_: any, link: string) => {
const command = extractCommand(link); try {
const extName = extractExtensionName(link); console.log(`Received add-extension event with link: ${link}`);
window.electron.logInfo(`Adding extension from deep link ${link}`); const command = extractCommand(link);
setPendingLink(link); const extName = extractExtensionName(link);
setModalMessage( window.electron.logInfo(`Adding extension from deep link ${link}`);
`Are you sure you want to install the ${extName} extension?\n\nCommand: ${command}` setPendingLink(link);
); setModalMessage(
setModalVisible(true); `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); window.electron.on('add-extension', handleAddExtension);
@@ -199,11 +277,14 @@ export default function App() {
// TODO: modify // TODO: modify
const handleConfirm = async () => { const handleConfirm = async () => {
if (pendingLink && !isInstalling) { if (pendingLink && !isInstalling) {
console.log(`Confirming installation of extension from: ${pendingLink}`);
setIsInstalling(true); setIsInstalling(true);
try { try {
await addExtensionFromDeepLink(pendingLink, setView); await addExtensionFromDeepLink(pendingLink, setView);
console.log('Extension installation successful');
} catch (error) { } catch (error) {
console.error('Failed to add extension:', error); console.error('Failed to add extension:', error);
// Consider showing a user-visible error notification here
} finally { } finally {
setModalVisible(false); setModalVisible(false);
setPendingLink(null); setPendingLink(null);
@@ -219,6 +300,7 @@ export default function App() {
setPendingLink(null); setPendingLink(null);
}; };
// TODO: remove
const { switchModel } = useModel(); // TODO: remove const { switchModel } = useModel(); // TODO: remove
const { addRecentModel } = useRecentModels(); // TODO: remove const { addRecentModel } = useRecentModels(); // TODO: remove
@@ -227,50 +309,71 @@ export default function App() {
return; return;
} }
// TODO: remove console.log('Non-alpha flow initializing...');
// Attempt to detect config for a stored provider // Attempt to detect config for a stored provider
const detectStoredProvider = () => { const detectStoredProvider = () => {
const config = window.electron.getConfig(); try {
const storedProvider = getStoredProvider(config); const config = window.electron.getConfig();
if (storedProvider) { console.log('Loaded config:', JSON.stringify(config));
setView('chat');
} else { const storedProvider = getStoredProvider(config);
setView('welcome'); 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 // Initialize system if we have a stored provider
const setupStoredProvider = async () => { const setupStoredProvider = async () => {
const config = window.electron.getConfig(); try {
const config = window.electron.getConfig();
if (config.GOOSE_PROVIDER && config.GOOSE_MODEL) { if (config.GOOSE_PROVIDER && config.GOOSE_MODEL) {
window.electron.logInfo( console.log('using GOOSE_PROVIDER and GOOSE_MODEL from config');
'Initializing system with environment: GOOSE_MODEL and GOOSE_PROVIDER as priority.' await initializeSystem(config.GOOSE_PROVIDER, config.GOOSE_MODEL);
); return;
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);
} }
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(); detectStoredProvider();
setupStoredProvider(); setupStoredProvider().catch((err) => {
console.error('ASYNC SETUP ERROR:', err);
setFatalError(`Async setup error: ${err.message || 'Unknown error'}`);
});
}, []); }, []);
// keep // keep