Skip to content

Commit

Permalink
Add options to choose agent versions to drop down menu
Browse files Browse the repository at this point in the history
  • Loading branch information
zakiali committed Dec 28, 2024
1 parent 50d8200 commit e25b887
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 24 deletions.
86 changes: 75 additions & 11 deletions ui/desktop/src/components/MoreMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import {Popover, PopoverContent, PopoverTrigger} from './ui/popover';
import VertDots from './ui/VertDots';
import {FaSun, FaMoon} from 'react-icons/fa';

interface VersionInfo {
current_version: string;
available_versions: string[];
}

export default function MoreMenu() {
const [open, setOpen] = useState(false);
const [versions, setVersions] = useState<VersionInfo | null>(null);
const [showVersions, setShowVersions] = useState(false);

const [useSystemTheme, setUseSystemTheme] = useState(() =>
localStorage.getItem('use_system_theme') === 'true'
Expand All @@ -19,6 +26,27 @@ export default function MoreMenu() {
return savedTheme ? savedTheme === 'dark' : systemPrefersDark;
});

useEffect(() => {
// Fetch available versions when the menu opens
const fetchVersions = async () => {
try {
const port = window.appConfig.get("GOOSE_SERVER__PORT");
const response = await fetch(`http://127.0.0.1:${port}/api/agent/versions`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setVersions(data);
} catch (error) {
console.error('Failed to fetch versions:', error);
}
};

if (open) {
fetchVersions();
}
}, [open]);

useEffect(() => {
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (useSystemTheme) {
Expand Down Expand Up @@ -52,6 +80,13 @@ export default function MoreMenu() {
localStorage.setItem('use_system_theme', checked.toString());
};

const handleVersionSelect = (version: string) => {
setOpen(false);
setShowVersions(false);
// Create a new chat window with the selected version
window.electron.createChatWindow(undefined, undefined, version);
};

return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
Expand All @@ -60,7 +95,7 @@ export default function MoreMenu() {
<VertDots size={18}/>
</button>
</PopoverTrigger>
<PopoverContent className="w-48 rounded-md">
<PopoverContent className="w-48 rounded-md" align="end">
<div className="flex flex-col bg-black text-white dark:bg-gray-800 rounded-md">
<div className="flex items-center justify-between p-2">
<span className="text-sm">Use System Theme</span>
Expand All @@ -77,21 +112,50 @@ export default function MoreMenu() {
? 'bg-gray-600 border-gray-600'
: 'bg-yellow-300 border-yellow-300'}`}
onClick={() => toggleTheme()}>
<span
className={`inline-block w-4 h-4 transform bg-white rounded-full transition-transform ${isDarkMode
? 'translate-x-6' : 'translate-x-1'}`}
>
{isDarkMode ? <FaMoon className="text-gray-200"/> : <FaSun
className="text-yellow-500"/>}
</span>
<span
className={`inline-block w-4 h-4 transform bg-white rounded-full transition-transform ${isDarkMode
? 'translate-x-6' : 'translate-x-1'}`}
>
{isDarkMode ? <FaMoon className="text-gray-200"/> : <FaSun
className="text-yellow-500"/>}
</span>
</button>
</div>)}

{/* Versions Menu */}
{versions && versions.available_versions.length > 0 && (
<>
<button
onClick={() => setShowVersions(!showVersions)}
className="w-full text-left px-2 py-1.5 text-sm hover:bg-gray-700 flex justify-between items-center"
>
<span>Versions</span>
<span className="text-xs">{showVersions ? '▼' : '▶'}</span>
</button>
{showVersions && (
<div className="pl-2 bg-gray-900">
{versions.available_versions.map((version) => (
<button
key={version}
onClick={() => handleVersionSelect(version)}
className={`w-full text-left px-2 py-1.5 text-sm hover:bg-gray-700 ${
version === versions.current_version ? 'text-green-400' : ''
}`}
>
{version} {version === versions.current_version && '(current)'}
</button>
))}
</div>
)}
</>
)}

<button
onClick={() => {
setOpen(false);
window.electron.directoryChooser();
}}
className="w-full text-left px-2 py-1.5 text-sm"
className="w-full text-left px-2 py-1.5 text-sm hover:bg-gray-700"
>
Open Directory (cmd+O)
</button>
Expand All @@ -100,12 +164,12 @@ export default function MoreMenu() {
setOpen(false);
window.electron.createChatWindow();
}}
className="w-full text-left px-2 py-1.5 text-sm"
className="w-full text-left px-2 py-1.5 text-sm hover:bg-gray-700"
>
New Session (cmd+N)
</button>
</div>
</PopoverContent>
</Popover>
);
}
}
9 changes: 6 additions & 3 deletions ui/desktop/src/goosed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const fetchAgentVersion = async (port: number): Promise<string> => {
};

// Goose process manager. Take in the app, port, and directory to start goosed in.
export const startGoosed = async (app, dir=null): Promise<[number, string, string]> => {
export const startGoosed = async (app, dir=null, env={}): Promise<[number, string, string]> => {
// In will use this later to determine if we should start process
const isDev = process.env.NODE_ENV === 'development';

Expand Down Expand Up @@ -73,13 +73,16 @@ export const startGoosed = async (app, dir=null): Promise<[number, string, strin
GOOSE_SERVER__PORT: String(port),

GOOSE_SERVER__SECRET_KEY: process.env.GOOSE_SERVER__SECRET_KEY,

// Add any additional environment variables passed in
...env
};

// Merge parent environment with additional environment variables
const env = { ...process.env, ...additionalEnv };
const processEnv = { ...process.env, ...additionalEnv };

// Spawn the goosed process with the user's home directory as cwd
const goosedProcess = spawn(goosedPath, [], { cwd: dir, env: env, stdio: ["ignore", "pipe", "pipe"] });
const goosedProcess = spawn(goosedPath, [], { cwd: dir, env: processEnv, stdio: ["ignore", "pipe", "pipe"] });

goosedProcess.stdout.on('data', (data) => {
log.info(`goosed stdout for port ${port} and dir ${dir}: ${data.toString()}`);
Expand Down
16 changes: 7 additions & 9 deletions ui/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const parseArgs = () => {
};

const checkApiCredentials = () => {

loadZshEnv(app.isPackaged);

//{env-macro-start}//
Expand Down Expand Up @@ -106,14 +105,15 @@ const createLauncher = () => {
});
};


// Track windows by ID
let windowCounter = 0;
const windowMap = new Map<number, BrowserWindow>();

const createChat = async (app, query?: string, dir?: string) => {

const [port, working_dir, agentVersion] = await startGoosed(app, dir);
const createChat = async (app, query?: string, dir?: string, version?: string) => {
// Add version to environment if specified
const env = version ? { GOOSE_AGENT_VERSION: version } : {};

const [port, working_dir, agentVersion] = await startGoosed(app, dir, env);
const mainWindow = new BrowserWindow({
titleBarStyle: 'hidden',
trafficLightPosition: { x: 16, y: 10 },
Expand Down Expand Up @@ -195,7 +195,6 @@ const createTray = () => {
tray.setContextMenu(contextMenu);
};


const showWindow = () => {
const windows = BrowserWindow.getAllWindows();

Expand Down Expand Up @@ -339,7 +338,6 @@ app.whenReady().then(async () => {
ipcMain.emit('create-chat-window');
},
}));

}

Menu.setApplicationMenu(menu);
Expand All @@ -350,8 +348,8 @@ app.whenReady().then(async () => {
}
});

ipcMain.on('create-chat-window', (_, query) => {
createChat(app, query);
ipcMain.on('create-chat-window', (_, query, dir, version) => {
createChat(app, query, dir, version);
});

ipcMain.on('directory-chooser', (_, replace: boolean = false) => {
Expand Down
2 changes: 1 addition & 1 deletion ui/desktop/src/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ contextBridge.exposeInMainWorld('electron', {
getConfig: () => config,
hideWindow: () => ipcRenderer.send('hide-window'),
directoryChooser: (replace) => ipcRenderer.send('directory-chooser', replace),
createChatWindow: (query) => ipcRenderer.send('create-chat-window', query),
createChatWindow: (query, dir, version) => ipcRenderer.send('create-chat-window', query, dir, version),
logInfo: (txt) => ipcRenderer.send('logInfo', txt),
showNotification: (data) => ipcRenderer.send('notify', data),
createWingToWingWindow: (query) => ipcRenderer.send('create-wing-to-wing-window', query),
Expand Down

0 comments on commit e25b887

Please sign in to comment.