diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index bbbfe8060..c7e80ace2 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -14,6 +14,7 @@ import { extractExtensionName } from './components/settings/extensions/utils'; import WelcomeView from './components/WelcomeView'; import ChatView from './components/ChatView'; import SettingsView, { type SettingsViewOptions } from './components/settings/SettingsView'; +import SettingsViewV2 from './components/settings_v2/SettingsView'; import MoreModelsView from './components/settings/models/MoreModelsView'; import ConfigureProvidersView from './components/settings/providers/ConfigureProvidersView'; import ProviderSettings from './components/settings/providers/providers/NewProviderSettingsPage'; @@ -28,7 +29,8 @@ export type View = | 'moreModels' | 'configureProviders' | 'configPage' - | 'alphaConfigureProviders'; + | 'alphaConfigureProviders' + | 'settingsV2'; export type ViewConfig = { view: View; @@ -202,15 +204,24 @@ export default function App() { }} /> )} - {view === 'settings' && ( - { - setView('chat'); - }} - setView={setView} - viewOptions={viewOptions as SettingsViewOptions} - /> - )} + {view === 'settings' && + (process.env.ALPHA ? ( + { + setView('chat'); + }} + setView={setView} + viewOptions={viewOptions as SettingsViewOptions} + /> + ) : ( + { + setView('chat'); + }} + setView={setView} + viewOptions={viewOptions as SettingsViewOptions} + /> + ))} {view === 'moreModels' && ( { diff --git a/ui/desktop/src/components/settings_v2/SettingsView.tsx b/ui/desktop/src/components/settings_v2/SettingsView.tsx new file mode 100644 index 000000000..b7b874cb7 --- /dev/null +++ b/ui/desktop/src/components/settings_v2/SettingsView.tsx @@ -0,0 +1,206 @@ +import React from 'react'; +import { ScrollArea } from '../ui/scroll-area'; +import BackButton from '../ui/BackButton'; +import type { View } from '../../App'; +import { Button } from '../ui/button'; +import { Switch } from '../ui/switch'; +import { Plus } from 'lucide-react'; +import { Gear } from '../icons/Gear'; +import { GPSIcon } from '../ui/icons'; + +interface ModelOption { + id: string; + name: string; + description: string; + selected: boolean; +} + +interface ExtensionItem { + id: string; + title: string; + subtitle: string; + enabled: boolean; + canConfigure?: boolean; +} + +// Mock data - replace with actual data source +const defaultModelOptions: ModelOption[] = [ + { + id: 'gpt-4', + name: 'GPT-4', + description: 'Most capable model, best for complex tasks', + selected: true, + }, + { + id: 'gpt-3.5', + name: 'GPT-3.5', + description: 'Fast and efficient for most tasks', + selected: false, + }, +]; + +const extensionItems: ExtensionItem[] = [ + { + id: 'dev', + title: 'Developer Tools', + subtitle: 'Code editing and shell access', + enabled: true, + canConfigure: true, + }, + { + id: 'browser', + title: 'Web Browser', + subtitle: 'Internet access and web automation', + enabled: false, + canConfigure: true, + }, +]; + +export type SettingsViewOptions = { + extensionId?: string; + showEnvVars?: boolean; +}; + +export default function SettingsView({ + onClose, + setView, + viewOptions, +}: { + onClose: () => void; + setView: (view: View) => void; + viewOptions: SettingsViewOptions; +}) { + const [modelOptions, setModelOptions] = React.useState(defaultModelOptions); + const [extensions, setExtensions] = React.useState(extensionItems); + + const handleModelSelect = (selectedId: string) => { + setModelOptions( + modelOptions.map((model) => ({ + ...model, + selected: model.id === selectedId, + })) + ); + }; + + const handleExtensionToggle = (id: string) => { + setExtensions( + extensions.map((extension) => ({ + ...extension, + enabled: extension.id === id ? !extension.enabled : extension.enabled, + })) + ); + }; + + return ( +
+
+ + +
+
+ onClose()} /> +
+ + {/* Content Area */} +
+
+ {/* Models Section */} +
+
+

Models

+
+
+
+ {modelOptions.map((model, index) => ( + +
+
+

{model.name}

+

{model.description}

+
+ handleModelSelect(model.id)} + className="h-4 w-4 text-white accent-[#393838] bg-[#393838] border-[#393838] checked:bg-[#393838] focus:ring-0 focus:ring-offset-0" + /> +
+ {index < modelOptions.length - 1 && ( +
+ )} + + ))} +
+
+ + +
+
+
+ + {/* Extensions Section */} +
+
+

Extensions

+
+
+

+ These extensions use the Model Context Protocol (MCP). They can expand Goose's + capabilities using three main components: Prompts, Resources, and Tools. +

+
+ {extensions.map((extension, index) => ( + +
+
+

{extension.title}

+

{extension.subtitle}

+
+
+ {extension.canConfigure && ( + + )} + handleExtensionToggle(extension.id)} + className="bg-[#393838] [&_span[data-state]]:bg-white" + /> +
+
+ {index < extensions.length - 1 &&
} + + ))} +
+
+ + +
+
+
+
+
+
+
+
+ ); +} diff --git a/ui/desktop/src/components/ui/BackButton.tsx b/ui/desktop/src/components/ui/BackButton.tsx index 2ff043420..c30a4950d 100644 --- a/ui/desktop/src/components/ui/BackButton.tsx +++ b/ui/desktop/src/components/ui/BackButton.tsx @@ -23,7 +23,7 @@ const BackButton: React.FC = ({ onClick, className = '' }) => { className={`flex items-center text-sm text-textSubtle group hover:text-textStandard ${className}`} > - Back + Exit ); };