Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 77 additions & 61 deletions ui/desktop/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import { ToastContainer } from 'react-toastify';
import { extractExtensionName } from './components/settings/extensions/utils';
import { GoosehintsModal } from './components/GoosehintsModal';
import { SessionDetails, fetchSessionDetails } from './sessions';

Check warning on line 14 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

'fetchSessionDetails' is defined but never used. Allowed unused vars must match /^_/u

import WelcomeView from './components/WelcomeView';
import ChatView from './components/ChatView';
Expand All @@ -24,12 +24,14 @@
import { useChat } from './hooks/useChat';

import 'react-toastify/dist/ReactToastify.css';
import { useConfig } from './components/ConfigContext';
import { FixedExtensionEntry, useConfig } from './components/ConfigContext';
import {
initializeBuiltInExtensions,
syncBuiltInExtensions,
addExtensionFromDeepLink as addExtensionFromDeepLinkV2,
addToAgentOnStartup,
} from './components/settings_v2/extensions';
import { extractExtensionConfig } from './components/settings_v2/extensions/utils';

// Views and their options
export type View =
Expand All @@ -50,7 +52,7 @@
| {
resumedSession?: SessionDetails;
}
| Record<string, any>;

Check warning on line 55 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
};

export default function App() {
Expand All @@ -74,6 +76,8 @@
}

// this is all settings v2 stuff
// Modified version of the alpha initialization flow for App.tsx

useEffect(() => {
// Skip if feature flag is not enabled
if (!process.env.ALPHA) {
Expand All @@ -82,24 +86,68 @@

console.log('Alpha flow initializing...');

const setupExtensions = async () => {
// First quickly check if we have model and provider to set chat view
const checkRequiredConfig = async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rearranged code into this otherwise we were stuck on onboarding page until extensions finished loading

try {
console.log('Setting up extensions...');
console.log('Reading GOOSE_PROVIDER and GOOSE_MODEL from config...');
const provider = (await read('GOOSE_PROVIDER', false)) as string;
const model = (await read('GOOSE_MODEL', false)) as string;

if (provider && model) {
// We have all needed configuration, set chat view immediately
console.log(`Found provider: ${provider}, model: ${model}, setting chat view`);
setView('chat');

// Initialize the system in background
initializeSystem(provider, model)
.then(() => console.log('System initialization successful'))
.catch((error) => {
console.error('Error initializing system:', error);
setFatalError(`System initialization error: ${error.message || 'Unknown error'}`);
setView('welcome');
});
} 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 checking configuration:', error);
setFatalError(`Configuration check error: ${error.message || 'Unknown error'}`);
setView('welcome');
}
};

// Set the ref immediately to prevent duplicate runs
initAttemptedRef.current = true;
console.log('Set initAttemptedRef to prevent duplicate runs');
// Setup extensions in parallel
const setupExtensions = async () => {
// Set the ref immediately to prevent duplicate runs
initAttemptedRef.current = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does anything read from this? It doesn't appear so. We can probably remove it.


let refreshedExtensions: FixedExtensionEntry[] = [];
try {
// Force refresh extensions from the backend to ensure we have the latest
console.log('Getting extensions from backend...');
const refreshedExtensions = await getExtensions(true);
refreshedExtensions = await getExtensions(true);
console.log(`Retrieved ${refreshedExtensions.length} extensions`);
} catch (error) {
console.log('Error getting extensions list');
return; // Exit early if we can't get the extensions list
}

// built-in extensions block -- just adds them to config if missing
try {
console.log('Setting up built-in 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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conceptual question.

If refreshedExtensions comes back the first time you ever boot the app as empty, is it any different/required to have a separate initializeBuiltInExtensions function? Could we just use a single syncBuiltInExtensions that behaves the same was as initialize if there were no extensions to begin with?

(No need to address this in this PR if it distracts - just trying to find opportunities to reduce complexity)

console.log('Built-in extensions initialization complete');

// Refresh the extensions list after initialization
refreshedExtensions = await getExtensions(true);
} else {
// Extensions exist, check for any missing built-ins
console.log('Checking for missing built-in extensions...');
Expand All @@ -109,70 +157,38 @@
}
} 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 provider: ${provider}, model: ${model}`);
await initializeSystem(provider, model);
console.log('System initialization successful');
setView('chat');
// now try to add to agent
console.log('Adding enabled extensions to agent...');
for (const extensionEntry of refreshedExtensions) {
if (extensionEntry.enabled) {
console.log(`Adding extension to agent: ${extensionEntry.name}`);
// need to convert to config because that's what the endpoint expects
const extensionConfig = extractExtensionConfig(extensionEntry);
// will handle toasts and also set failures to enabled = false
await addToAgentOnStartup({ addToConfig: addExtension, extensionConfig });
} 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');
console.log(`Skipping disabled extension: ${extensionEntry.name}`);
}
} 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');
}

console.log('Extensions setup complete');
};

// 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
// Execute the two flows in parallel for speed
checkRequiredConfig().catch((error) => {
console.error('Unhandled error in checkRequiredConfig:', error);
setFatalError(`Config check error: ${error.message || 'Unknown error'}`);
});

setupExtensions().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

Check warning on line 190 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

React Hook useEffect has missing dependencies: 'addExtension', 'getExtensions', and 'read'. Either include them or remove the dependency array
const setView = (view: View, viewOptions: Record<any, any> = {}) => {

Check warning on line 191 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type

Check warning on line 191 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
console.log(`Setting view to: ${view}`, viewOptions);
setInternalView({ view, viewOptions });
};
Expand Down Expand Up @@ -215,7 +231,7 @@

useEffect(() => {
console.log('Setting up fatal error handler');
const handleFatalError = (_: any, errorMessage: string) => {

Check warning on line 234 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
console.error('Encountered a fatal error: ', errorMessage);
// Log additional context that might help diagnose the issue
console.error('Current view:', view);
Expand Down Expand Up @@ -252,7 +268,7 @@
// TODO: modify
useEffect(() => {
console.log('Setting up extension handler');
const handleAddExtension = (_: any, link: string) => {

Check warning on line 271 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
try {
console.log(`Received add-extension event with link: ${link}`);
const command = extractCommand(link);
Expand Down Expand Up @@ -376,7 +392,7 @@
console.error('ASYNC SETUP ERROR:', err);
setFatalError(`Async setup error: ${err.message || 'Unknown error'}`);
});
}, []);

Check warning on line 395 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

React Hook useEffect has missing dependencies: 'addRecentModel' and 'switchModel'. Either include them or remove the dependency array

// keep
if (fatalError) {
Expand Down
4 changes: 0 additions & 4 deletions ui/desktop/src/components/settings_v2/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ export default function SettingsView({
setView: (view: View) => void;
viewOptions: SettingsViewOptions;
}) {
const { config } = useConfig();

console.log(config);

return (
<div className="h-screen w-full">
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
Expand Down
Loading
Loading