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
8 changes: 8 additions & 0 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 Down Expand Up @@ -49,7 +49,7 @@
| {
resumedSession?: SessionDetails;
}
| Record<string, any>;

Check warning on line 52 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 Down Expand Up @@ -170,9 +170,9 @@
'Initializing system with environment: GOOSE_MODEL and GOOSE_PROVIDER as priority.'
);
await initializeSystem(config.GOOSE_PROVIDER, config.GOOSE_MODEL);
return;

Check warning on line 173 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 storedProvider = getStoredProvider(config);

Check warning on line 175 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 175 in ui/desktop/src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
const storedModel = getStoredModel();
if (storedProvider) {
try {
Expand Down Expand Up @@ -215,7 +215,7 @@

// Add cleanup for session states when view changes
useEffect(() => {
if (view !== 'chat') {

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

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
setIsLoadingSession(false);
}
}, [view]);
Expand Down Expand Up @@ -252,10 +252,18 @@
</div>
);

return (

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

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

Unexpected any. Specify a different type
<>
<ToastContainer
aria-label="Toast notifications"
toastClassName={() =>
`relative min-h-16 mb-4 p-2 rounded-lg
flex justify-between overflow-hidden cursor-pointer
text-textProminentInverse bg-bgStandardInverse dark:bg-bgAppInverse
`
}
style={{ width: '380px' }}
className="mt-6"
position="top-right"
autoClose={3000}
closeOnClick
Expand Down
67 changes: 39 additions & 28 deletions ui/desktop/src/agent/UpdateAgent.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { useConfig, FixedExtensionEntry } from '../components/ConfigContext';

Check warning on line 1 in ui/desktop/src/agent/UpdateAgent.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

'FixedExtensionEntry' is defined but never used. Allowed unused vars must match /^_/u
import { getApiUrl, getSecretKey } from '../config';
import { ExtensionConfig } from '../api';
import { toast } from 'react-toastify';
import React, { useState } from 'react';

Check warning on line 5 in ui/desktop/src/agent/UpdateAgent.tsx

View workflow job for this annotation

GitHub Actions / Lint Electron Desktop App

'React' is defined but never used. Allowed unused vars must match /^_/u
import { initializeAgent as startAgent, replaceWithShims } from './utils';
import {
ToastError,
ToastInfo,
ToastLoading,
ToastSuccess,
} from '../components/settings/models/toasts';

// extensionUpdate = an extension was newly added or updated so we should attempt to add it

Expand All @@ -25,9 +31,10 @@
return true;
} catch (error) {
console.error('Failed to initialize agent:', error);
toast.error(
`Failed to initialize agent: ${error instanceof Error ? error.message : 'Unknown error'}`
);
ToastError({
title: 'Failed to initialize agent',
errorMessage: error instanceof Error ? error.message : 'Unknown error',
});
return false;
}
};
Expand Down Expand Up @@ -84,10 +91,14 @@
try {
let toastId;
if (!silent) {
toastId = toast.loading(`Adding ${extension.name} extension...`, {
position: 'top-center',
toastId = ToastLoading({
title: extension.name,
msg: 'Adding extension...',
toastOptions: { position: 'top-center' },
});
ToastInfo({
msg: 'Press the escape key to continue using goose while extension loads',
});
toast.info('Press the escape key to continue using goose while extension loads');
}

const response = await fetch(getApiUrl('/extensions/add'), {
Expand All @@ -108,14 +119,20 @@
if (response.status === 428) {
if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.error('Agent is not initialized. Please initialize the agent first.');
ToastError({
msg: 'Agent is not initialized. Please initialize the agent first.',
});
}
return response;
}

if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.error(`Failed to add ${extension.name} extension: ${errorMsg}`);
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: errorMsg,
});
}
return response;
}
Expand All @@ -135,40 +152,34 @@
if (!data.error) {
if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.success(`Successfully enabled ${extension.name} extension`);
ToastSuccess({
title: extension.name,
msg: 'Successfully added extension',
});
}
return response;
}

console.log('Error trying to send a request to the extensions endpoint');
const errorMessage = `Error adding ${extension.name} extension${data.message ? `. ${data.message}` : ''}`;
const ErrorMsg = ({ closeToast }: { closeToast?: () => void }) => (
<div className="flex flex-col gap-1">
<div>Error adding {extension.name} extension</div>
<div>
<button
className="text-sm rounded px-2 py-1 bg-gray-400 hover:bg-gray-300 text-white cursor-pointer"
onClick={() => {
navigator.clipboard.writeText(data.message || 'Unknown error');
closeToast?.();
}}
>
Copy error message
</button>
</div>
</div>
);

console.error(errorMessage);
if (toastId) toast.dismiss(toastId);
toast(ErrorMsg, { type: 'error', autoClose: false });
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: data.message,
});

return response;
} catch (error) {
console.log('Got some other error');
const errorMessage = `Failed to add ${extension.name} extension: ${error instanceof Error ? error.message : 'Unknown error'}`;
console.error(errorMessage);
toast.error(errorMessage, { autoClose: false });
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: error.message,
});
throw error;
}
};
Expand Down
1 change: 1 addition & 0 deletions ui/desktop/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getTextContent,
createAssistantMessage,
} from '../types/message';
import { ToastSuccess } from './settings/models/toasts';

export interface ChatType {
id: string;
Expand Down
26 changes: 14 additions & 12 deletions ui/desktop/src/components/ProviderGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { createSelectedModel } from './settings/models/utils';
import { getDefaultModel } from './settings/models/hardcoded_stuff';
import { initializeSystem } from '../utils/providerUtils';
import { getApiUrl, getSecretKey } from '../config';
import { toast } from 'react-toastify';
import { getActiveProviders, isSecretKey } from './settings/api_keys/utils';
import { BaseProviderGrid, getProviderDescription } from './settings/providers/BaseProviderGrid';
import { ToastError, ToastSuccess } from './settings/models/toasts';

interface ProviderGridProps {
onSubmit?: () => void;
Expand Down Expand Up @@ -55,9 +55,10 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
addRecentModel(model);
localStorage.setItem('GOOSE_PROVIDER', providerId);

toast.success(
`Selected ${provider.name} provider. Starting Goose with default model: ${getDefaultModel(provider.name.toLowerCase().replace(/ /g, '_'))}.`
);
ToastSuccess({
title: provider.name,
msg: `Starting Goose with default model: ${getDefaultModel(provider.name.toLowerCase().replace(/ /g, '_'))}.`,
});

onSubmit?.();
};
Expand Down Expand Up @@ -134,11 +135,10 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
}
}

toast.success(
isUpdate
? `Successfully updated configuration for ${provider}`
: `Successfully added configuration for ${provider}`
);
ToastSuccess({
title: provider,
msg: isUpdate ? `Successfully updated configuration` : `Successfully added configuration`,
});

const updatedKeys = await getActiveProviders();
setActiveKeys(updatedKeys);
Expand All @@ -147,9 +147,11 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
setSelectedId(null);
} catch (error) {
console.error('Error handling modal submit:', error);
toast.error(
`Failed to ${providers.find((p) => p.id === selectedId)?.isConfigured ? 'update' : 'add'} configuration for ${provider}`
);
ToastError({
title: provider,
msg: `Failed to ${providers.find((p) => p.id === selectedId)?.isConfigured ? 'update' : 'add'} configuration`,
errorMessage: error.message,
});
}
};

Expand Down
7 changes: 5 additions & 2 deletions ui/desktop/src/components/settings/SettingsView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react';
import { ScrollArea } from '../ui/scroll-area';
import { toast } from 'react-toastify';
import { Settings as SettingsType } from './types';
import {
FullExtensionConfig,
Expand All @@ -16,6 +15,7 @@ import { RecentModelsRadio } from './models/RecentModels';
import { ExtensionItem } from './extensions/ExtensionItem';
import type { View } from '../../App';
import { ModeSelection } from './basic/ModeSelection';
import { ToastSuccess } from './models/toasts';

const EXTENSIONS_DESCRIPTION =
'The Model Context Protocol (MCP) is a system that allows AI models to securely connect with local or remote resources using standard server setups. It works like a client-server setup and expands AI capabilities using three main components: Prompts, Resources, and Tools.';
Expand Down Expand Up @@ -164,7 +164,10 @@ export default function SettingsView({
const response = await removeExtension(extensionBeingConfigured.name, true);

if (response.ok) {
toast.success(`Successfully removed ${extensionBeingConfigured.name} extension`);
ToastSuccess({
title: extensionBeingConfigured.name,
msg: `Successfully removed extension`,
});

// Remove from localstorage
setSettings((prev) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FullExtensionConfig } from '../../../extensions';
import { getApiUrl, getSecretKey } from '../../../config';
import { addExtension } from '../../../extensions';
import { toast } from 'react-toastify';
import { ToastError, ToastSuccess } from '../models/toasts';

interface ConfigureExtensionModalProps {
isOpen: boolean;
Expand Down Expand Up @@ -68,12 +69,19 @@ export function ConfigureBuiltInExtensionModal({
throw new Error('Failed to add system configuration');
}

toast.success(`Successfully configured the ${extension.name} extension`);
ToastSuccess({
title: extension.name,
msg: `Successfully configured extension`,
});
onSubmit();
onClose();
} catch (error) {
console.error('Error configuring extension:', error);
toast.error('Failed to configure extension');
ToastError({
title: extension.name,
msg: `Failed to configure the extension`,
errorMessage: error.message,
});
} finally {
setIsSubmitting(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FullExtensionConfig } from '../../../extensions';
import { getApiUrl, getSecretKey } from '../../../config';
import { addExtension } from '../../../extensions';
import { toast } from 'react-toastify';
import { ToastError, ToastSuccess } from '../models/toasts';

interface ConfigureExtensionModalProps {
isOpen: boolean;
Expand Down Expand Up @@ -70,12 +71,19 @@ export function ConfigureExtensionModal({
throw new Error('Failed to add system configuration');
}

toast.success(`Successfully configured the ${extension.name} extension`);
ToastSuccess({
title: extension.name,
msg: `Successfully configured extension`,
});
onSubmit();
onClose();
} catch (error) {
console.error('Error configuring extension:', error);
toast.error('Failed to configure extension');
ToastError({
title: extension.name,
msg: `Failed to configure extension`,
errorMessage: error.message,
});
} finally {
setIsSubmitting(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { toast } from 'react-toastify';
import Select from 'react-select';
import { createDarkSelectStyles, darkSelectTheme } from '../../ui/select-styles';
import { getApiUrl, getSecretKey } from '../../../config';
import { ToastError } from '../models/toasts';

interface ManualExtensionModalProps {
isOpen: boolean;
Expand Down Expand Up @@ -38,22 +39,22 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
e.preventDefault();

if (!formData.id || !formData.name || !formData.description) {
toast.error('Please fill in all required fields');
ToastError({ title: 'Please fill in all required fields' });
return;
}

if (formData.type === 'stdio' && !formData.commandInput) {
toast.error('Command is required for stdio type');
ToastError({ title: 'Command is required for stdio type' });
return;
}

if (formData.type === 'sse' && !formData.uri) {
toast.error('URI is required for SSE type');
ToastError({ title: 'URI is required for SSE type' });
return;
}

if (formData.type === 'builtin' && !formData.name) {
toast.error('Name is required for builtin type');
ToastError({ title: 'Name is required for builtin type' });
return;
}

Expand Down Expand Up @@ -98,7 +99,7 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
resetForm();
} catch (error) {
console.error('Error configuring extension:', error);
toast.error('Failed to configure extension');
ToastError({ title: 'Failed to configure extension', errorMessage: error.message });
}
};

Expand Down
Loading