ui: add logs to app (#1760)
This commit is contained in:
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user