From a7758acd68a708f3a4da1081447ca4d991d32b1b Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 11:59:46 +1100 Subject: [PATCH 1/9] WIP: feature flags --- ui/desktop/src/components/Splash.tsx | 23 ++++++++++++++--- ui/desktop/src/featureFlags.ts | 38 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 ui/desktop/src/featureFlags.ts diff --git a/ui/desktop/src/components/Splash.tsx b/ui/desktop/src/components/Splash.tsx index 1aa60efcc..333e5ba74 100644 --- a/ui/desktop/src/components/Splash.tsx +++ b/ui/desktop/src/components/Splash.tsx @@ -1,8 +1,23 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import GooseSplashLogo from './GooseSplashLogo'; import SplashPills from './SplashPills'; +import { featureFlags } from '../featureFlags'; export default function Splash({ append }) { + const [whatCanGooseDoText, setWhatCanGooseDoText] = useState(featureFlags.getFlags().whatCanGooseDoText); + + // Update the text when feature flags change + useEffect(() => { + const updateInterval = setInterval(() => { + const currentText = featureFlags.getFlags().whatCanGooseDoText; + if (currentText !== whatCanGooseDoText) { + setWhatCanGooseDoText(currentText); + } + }, 1000); + + return () => clearInterval(updateInterval); + }, [whatCanGooseDoText]); + return (
@@ -17,13 +32,13 @@ export default function Splash({ append }) { className="w-[312px] px-16 py-4 text-14 text-center text-splash-pills-text dark:text-splash-pills-text-dark whitespace-nowrap cursor-pointer bg-prev-goose-gradient dark:bg-dark-prev-goose-gradient text-prev-goose-text dark:text-prev-goose-text-dark rounded-[14px] inline-block hover:scale-[1.02] transition-all duration-150" onClick={async () => { const message = { - content: "What can Goose do?", + content: whatCanGooseDoText, role: "user", }; await append(message); }} > - What can goose do? + {whatCanGooseDoText}
@@ -34,4 +49,4 @@ export default function Splash({ append }) {
) -} +} \ No newline at end of file diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts new file mode 100644 index 000000000..2610962ab --- /dev/null +++ b/ui/desktop/src/featureFlags.ts @@ -0,0 +1,38 @@ +interface FeatureFlags { + whatCanGooseDoText: string; + // Add more feature flags here as needed +} + +class FeatureFlagsManager { + private static instance: FeatureFlagsManager; + private flags: FeatureFlags; + + private constructor() { + this.flags = { + whatCanGooseDoText: "What can goose do?", + }; + + // Make feature flags available in the developer console + if (typeof window !== 'undefined') { + (window as any).featureFlags = this.flags; + } + } + + public static getInstance(): FeatureFlagsManager { + if (!FeatureFlagsManager.instance) { + FeatureFlagsManager.instance = new FeatureFlagsManager(); + } + return FeatureFlagsManager.instance; + } + + public getFlags(): FeatureFlags { + return this.flags; + } + + public updateFlag(key: K, value: FeatureFlags[K]): void { + this.flags[key] = value; + } +} + +export const featureFlags = FeatureFlagsManager.getInstance(); +export type { FeatureFlags }; \ No newline at end of file From da1a7dd07db0d96f2aa65fe5b19868677a2497ef Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 13:40:41 +1100 Subject: [PATCH 2/9] GUI menu for feature flag --- ui/desktop/src/App.tsx | 7 ++- ui/desktop/src/components/Splash.tsx | 19 ++++---- ui/desktop/src/featureFlags.ts | 22 +++++++++ ui/desktop/src/main.ts | 9 ++++ ui/desktop/src/preload.js | 6 ++- ui/desktop/src/windows/featureFlags.html | 11 +++++ ui/desktop/src/windows/featureFlags.tsx | 36 ++++++++++++++ ui/desktop/src/windows/featureFlagsWindow.ts | 49 ++++++++++++++++++++ ui/desktop/vite.config.mts | 1 + 9 files changed, 147 insertions(+), 13 deletions(-) create mode 100644 ui/desktop/src/windows/featureFlags.html create mode 100644 ui/desktop/src/windows/featureFlags.tsx create mode 100644 ui/desktop/src/windows/featureFlagsWindow.ts diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 36c6d27dc..5f4a7f948 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -2,11 +2,12 @@ import React, { useEffect, useState } from 'react'; import LauncherWindow from './LauncherWindow'; import ChatWindow from './ChatWindow'; import ErrorScreen from './components/ErrorScreen'; +import FeatureFlagsWindow from './windows/featureFlags'; export default function App() { const [fatalError, setFatalError] = useState(null); const searchParams = new URLSearchParams(window.location.search); - const isLauncher = searchParams.get('window') === 'launcher'; + const targetWindow = searchParams.get('window'); useEffect(() => { const handleFatalError = (_: any, errorMessage: string) => { @@ -25,8 +26,10 @@ export default function App() { return window.electron.reloadApp()} />; } - if (isLauncher) { + if (targetWindow === 'launcher') { return ; + } else if (targetWindow === 'featureFlags') { + return ; } else { return ; } diff --git a/ui/desktop/src/components/Splash.tsx b/ui/desktop/src/components/Splash.tsx index 333e5ba74..036231ccb 100644 --- a/ui/desktop/src/components/Splash.tsx +++ b/ui/desktop/src/components/Splash.tsx @@ -1,22 +1,23 @@ import React, { useState, useEffect } from 'react'; import GooseSplashLogo from './GooseSplashLogo'; import SplashPills from './SplashPills'; -import { featureFlags } from '../featureFlags'; +import { featureFlags, type FeatureFlags } from '../featureFlags'; export default function Splash({ append }) { - const [whatCanGooseDoText, setWhatCanGooseDoText] = useState(featureFlags.getFlags().whatCanGooseDoText); + const [flags, setFlags] = useState(featureFlags.getFlags()); - // Update the text when feature flags change + // Update all feature flags when they change useEffect(() => { const updateInterval = setInterval(() => { - const currentText = featureFlags.getFlags().whatCanGooseDoText; - if (currentText !== whatCanGooseDoText) { - setWhatCanGooseDoText(currentText); + const currentFlags = featureFlags.getFlags(); + // Deep comparison to avoid unnecessary updates + if (JSON.stringify(currentFlags) !== JSON.stringify(flags)) { + setFlags(currentFlags); } }, 1000); return () => clearInterval(updateInterval); - }, [whatCanGooseDoText]); + }, [flags]); return (
@@ -32,13 +33,13 @@ export default function Splash({ append }) { className="w-[312px] px-16 py-4 text-14 text-center text-splash-pills-text dark:text-splash-pills-text-dark whitespace-nowrap cursor-pointer bg-prev-goose-gradient dark:bg-dark-prev-goose-gradient text-prev-goose-text dark:text-prev-goose-text-dark rounded-[14px] inline-block hover:scale-[1.02] transition-all duration-150" onClick={async () => { const message = { - content: whatCanGooseDoText, + content: flags.whatCanGooseDoText, role: "user", }; await append(message); }} > - {whatCanGooseDoText} + {flags.whatCanGooseDoText}
diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index 2610962ab..6197cbeb5 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -6,10 +6,14 @@ interface FeatureFlags { class FeatureFlagsManager { private static instance: FeatureFlagsManager; private flags: FeatureFlags; + private readonly STORAGE_KEY = 'goose-feature-flags'; private constructor() { + // Load flags from storage or use defaults + const savedFlags = this.loadFlags(); this.flags = { whatCanGooseDoText: "What can goose do?", + ...savedFlags }; // Make feature flags available in the developer console @@ -18,6 +22,23 @@ class FeatureFlagsManager { } } + private loadFlags(): Partial { + try { + const saved = localStorage.getItem(this.STORAGE_KEY); + return saved ? JSON.parse(saved) : {}; + } catch { + return {}; + } + } + + private saveFlags(): void { + try { + localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.flags)); + } catch (error) { + console.error('Failed to save feature flags:', error); + } + } + public static getInstance(): FeatureFlagsManager { if (!FeatureFlagsManager.instance) { FeatureFlagsManager.instance = new FeatureFlagsManager(); @@ -31,6 +52,7 @@ class FeatureFlagsManager { public updateFlag(key: K, value: FeatureFlags[K]): void { this.flags[key] = value; + this.saveFlags(); } } diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 86c9c2b34..09d95cf6e 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -7,6 +7,7 @@ import started from "electron-squirrel-startup"; import log from './utils/logger'; import { exec } from 'child_process'; import { addRecentDir, loadRecentDirs } from './utils/recentDirs'; +import { createFeatureFlagsWindow } from './windows/featureFlagsWindow'; // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (started) app.quit(); @@ -333,6 +334,14 @@ app.whenReady().then(async () => { } + // Add Feature Flags menu item + fileMenu?.submenu?.append(new MenuItem({ + label: 'Feature Flags', + click() { + createFeatureFlagsWindow(); + }, + })); + Menu.setApplicationMenu(menu); app.on('activate', () => { diff --git a/ui/desktop/src/preload.js b/ui/desktop/src/preload.js index 3c98e5b33..f0208d82f 100644 --- a/ui/desktop/src/preload.js +++ b/ui/desktop/src/preload.js @@ -20,12 +20,14 @@ contextBridge.exposeInMainWorld('electron', { reloadApp: () => ipcRenderer.send('reload-app'), selectFileOrDirectory: () => ipcRenderer.invoke('select-file-or-directory'), on: (channel, callback) => { - if (channel === 'fatal-error') { + const validChannels = ['fatal-error', 'update-feature-flags']; + if (validChannels.includes(channel)) { ipcRenderer.on(channel, callback); } }, off: (channel, callback) => { - if (channel === 'fatal-error') { + const validChannels = ['fatal-error', 'update-feature-flags']; + if (validChannels.includes(channel)) { ipcRenderer.removeListener(channel, callback); } } diff --git a/ui/desktop/src/windows/featureFlags.html b/ui/desktop/src/windows/featureFlags.html new file mode 100644 index 000000000..c9f090361 --- /dev/null +++ b/ui/desktop/src/windows/featureFlags.html @@ -0,0 +1,11 @@ + + + + + Feature Flags + + +
+ + + \ No newline at end of file diff --git a/ui/desktop/src/windows/featureFlags.tsx b/ui/desktop/src/windows/featureFlags.tsx new file mode 100644 index 000000000..b83e39302 --- /dev/null +++ b/ui/desktop/src/windows/featureFlags.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { featureFlags, type FeatureFlags } from '../featureFlags'; + +export default function FeatureFlagsWindow() { + const [flags, setFlags] = React.useState(featureFlags.getFlags()); + + const handleFlagChange = (key: keyof FeatureFlags, value: any) => { + featureFlags.updateFlag(key, value); + setFlags({ ...featureFlags.getFlags() }); + }; + + return ( +
+
+

Feature Flags

+
+ {Object.entries(flags).map(([key, value]) => ( +
+ + { + const newValue = typeof value === 'boolean' ? e.target.checked : e.target.value; + handleFlagChange(key as keyof FeatureFlags, newValue); + }} + className="border rounded p-2 dark:bg-gray-800 dark:border-gray-700" + /> +
+ ))} +
+
+
+ ); +} \ No newline at end of file diff --git a/ui/desktop/src/windows/featureFlagsWindow.ts b/ui/desktop/src/windows/featureFlagsWindow.ts new file mode 100644 index 000000000..9812506c3 --- /dev/null +++ b/ui/desktop/src/windows/featureFlagsWindow.ts @@ -0,0 +1,49 @@ +import { BrowserWindow } from 'electron'; +import path from 'node:path'; + +declare const MAIN_WINDOW_VITE_DEV_SERVER_URL: string; +declare const MAIN_WINDOW_VITE_NAME: string; + +let featureFlagsWindow: BrowserWindow | null = null; + +export const createFeatureFlagsWindow = () => { + // Don't create multiple windows + if (featureFlagsWindow) { + featureFlagsWindow.focus(); + return; + } + + featureFlagsWindow = new BrowserWindow({ + width: 400, + height: 600, + title: 'Feature Flags', + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + nodeIntegration: false, + contextIsolation: true, + }, + }); + + // Open dev tools in development + if (process.env.NODE_ENV === 'development') { + featureFlagsWindow.webContents.openDevTools(); + } + + const launcherParams = '?window=featureFlags'; + if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { + featureFlagsWindow.loadURL(`${MAIN_WINDOW_VITE_DEV_SERVER_URL}${launcherParams}`); + } else { + featureFlagsWindow.loadFile( + path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html${launcherParams}`) + ); + } + + featureFlagsWindow.on('closed', () => { + featureFlagsWindow = null; + }); + + // Log any load failures + featureFlagsWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => { + console.error('Failed to load feature flags window:', errorCode, errorDescription); + }); +}; \ No newline at end of file diff --git a/ui/desktop/vite.config.mts b/ui/desktop/vite.config.mts index fb6c807a1..2ee3b19f2 100644 --- a/ui/desktop/vite.config.mts +++ b/ui/desktop/vite.config.mts @@ -10,6 +10,7 @@ export default defineConfig({ input: { main: resolve(__dirname, 'src/main.ts'), index: resolve(__dirname, 'index.html'), + featureFlags: resolve(__dirname, 'src/windows/featureFlags.html'), }, }, }, From d3c9911e01ecba61a61c771f3e08c890adf97f30 Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 14:31:12 +1100 Subject: [PATCH 3/9] expanded tool outputs flag --- ui/desktop/src/components/ToolInvocations.tsx | 15 ++++++++++++--- ui/desktop/src/featureFlags.ts | 2 ++ ui/desktop/src/windows/featureFlags.tsx | 3 +++ ui/desktop/src/windows/featureFlagsWindow.ts | 5 ----- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ui/desktop/src/components/ToolInvocations.tsx b/ui/desktop/src/components/ToolInvocations.tsx index a2abec278..baf27547d 100644 --- a/ui/desktop/src/components/ToolInvocations.tsx +++ b/ui/desktop/src/components/ToolInvocations.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Card } from './ui/card'; -import Box from './ui/Box' +import Box from './ui/Box'; +import { featureFlags } from '../featureFlags'; import { ToolCallArguments } from "./ToolCallArguments" import MarkdownContent from './MarkdownContent' import { snakeToTitleCase } from '../utils' @@ -85,8 +86,16 @@ interface ToolResultProps { } function ToolResult({ result }: ToolResultProps) { - // State to track expanded items - const [expandedItems, setExpandedItems] = React.useState([]); + const expandedToolsByDefault = featureFlags.getFlags().expandedToolsByDefault; + + // Initialize expanded state based on feature flag + const [expandedItems, setExpandedItems] = React.useState(() => { + if (expandedToolsByDefault) { + // If flag is on, start with all items expanded + return result?.result ? Array.from(Array(Array.isArray(result.result) ? result.result.length : 1).keys()) : []; + } + return []; // If flag is off, start with all items collapsed + }); // If no result info, don't show anything if (!result || !result.result) return null; diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index 6197cbeb5..1883fa100 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -1,5 +1,6 @@ interface FeatureFlags { whatCanGooseDoText: string; + expandedToolsByDefault: boolean; // Add more feature flags here as needed } @@ -13,6 +14,7 @@ class FeatureFlagsManager { const savedFlags = this.loadFlags(); this.flags = { whatCanGooseDoText: "What can goose do?", + expandedToolsByDefault: false, ...savedFlags }; diff --git a/ui/desktop/src/windows/featureFlags.tsx b/ui/desktop/src/windows/featureFlags.tsx index b83e39302..7d94fa424 100644 --- a/ui/desktop/src/windows/featureFlags.tsx +++ b/ui/desktop/src/windows/featureFlags.tsx @@ -31,6 +31,9 @@ export default function FeatureFlagsWindow() { ))}
+
+ Flag changes are saved immediately. Open a new chat window to use the changes. +
); } \ No newline at end of file diff --git a/ui/desktop/src/windows/featureFlagsWindow.ts b/ui/desktop/src/windows/featureFlagsWindow.ts index 9812506c3..7f18286b2 100644 --- a/ui/desktop/src/windows/featureFlagsWindow.ts +++ b/ui/desktop/src/windows/featureFlagsWindow.ts @@ -24,11 +24,6 @@ export const createFeatureFlagsWindow = () => { }, }); - // Open dev tools in development - if (process.env.NODE_ENV === 'development') { - featureFlagsWindow.webContents.openDevTools(); - } - const launcherParams = '?window=featureFlags'; if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { featureFlagsWindow.loadURL(`${MAIN_WINDOW_VITE_DEV_SERVER_URL}${launcherParams}`); From 7b2501e49863a97c00bb777f9f69fc3902d8787c Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 14:47:47 +1100 Subject: [PATCH 4/9] only load stored values with existing keys --- ui/desktop/src/featureFlags.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index 1883fa100..07dd2e99b 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -10,14 +10,26 @@ class FeatureFlagsManager { private readonly STORAGE_KEY = 'goose-feature-flags'; private constructor() { - // Load flags from storage or use defaults - const savedFlags = this.loadFlags(); - this.flags = { + // Define default flags + const defaultFlags: FeatureFlags = { whatCanGooseDoText: "What can goose do?", expandedToolsByDefault: false, - ...savedFlags }; + // Load flags from storage + const savedFlags = this.loadFlags(); + + // Create a new flags object starting with default values + this.flags = { ...defaultFlags }; + + // Only override with saved values for keys that exist in default flags + Object.keys(defaultFlags).forEach((key) => { + const typedKey = key as keyof FeatureFlags; + if (savedFlags.hasOwnProperty(key)) { + this.flags[typedKey] = savedFlags[typedKey]; + } + }); + // Make feature flags available in the developer console if (typeof window !== 'undefined') { (window as any).featureFlags = this.flags; From d0246d1f7c6da91a689cc344dfc200ea3a867f3e Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 15:04:26 +1100 Subject: [PATCH 5/9] Better feature flag styling --- ui/desktop/src/windows/featureFlags.tsx | 91 +++++++++++++++----- ui/desktop/src/windows/featureFlagsWindow.ts | 6 +- 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/ui/desktop/src/windows/featureFlags.tsx b/ui/desktop/src/windows/featureFlags.tsx index 7d94fa424..1f562db3c 100644 --- a/ui/desktop/src/windows/featureFlags.tsx +++ b/ui/desktop/src/windows/featureFlags.tsx @@ -1,5 +1,8 @@ import React from 'react'; import { featureFlags, type FeatureFlags } from '../featureFlags'; +import { Card } from '../components/ui/card'; +import { Input } from '../components/ui/input'; +import Box from '../components/ui/Box'; export default function FeatureFlagsWindow() { const [flags, setFlags] = React.useState(featureFlags.getFlags()); @@ -10,30 +13,78 @@ export default function FeatureFlagsWindow() { }; return ( -
-
-

Feature Flags

+
+ {/* Draggable title bar */} +
+ +
- {Object.entries(flags).map(([key, value]) => ( -
- - { - const newValue = typeof value === 'boolean' ? e.target.checked : e.target.value; - handleFlagChange(key as keyof FeatureFlags, newValue); - }} - className="border rounded p-2 dark:bg-gray-800 dark:border-gray-700" - /> +
+ +
+

Feature Flags

+

+ Configure experimental features and settings +

- ))} +
+ + +
+ {Object.entries(flags).map(([key, value]) => ( +
+
+
+ + + {key.split(/(?=[A-Z])/).join(" ")} + +
+ {typeof value === 'boolean' ? ( + + ) : ( + handleFlagChange(key as keyof FeatureFlags, e.target.value)} + className="max-w-[300px] h-7 text-xs" + /> + )} +
+

+ {getFeatureFlagDescription(key)} +

+
+ ))} +
+
+ + +
+ +

+ ⚡️ Tip: Open a new chat window to see your changes take effect +

+
+
-
- Flag changes are saved immediately. Open a new chat window to use the changes. -
); +} + +function getFeatureFlagDescription(key: string): string { + const descriptions: Record = { + whatCanGooseDoText: "Customize the placeholder text shown in the chat input field", + expandedToolsByDefault: "Show tool outputs expanded by default instead of collapsed" + }; + return descriptions[key] || "No description available"; } \ No newline at end of file diff --git a/ui/desktop/src/windows/featureFlagsWindow.ts b/ui/desktop/src/windows/featureFlagsWindow.ts index 7f18286b2..30360de5b 100644 --- a/ui/desktop/src/windows/featureFlagsWindow.ts +++ b/ui/desktop/src/windows/featureFlagsWindow.ts @@ -14,14 +14,16 @@ export const createFeatureFlagsWindow = () => { } featureFlagsWindow = new BrowserWindow({ - width: 400, - height: 600, + width: 800, + height: 700, title: 'Feature Flags', webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: false, contextIsolation: true, }, + titleBarStyle: 'hidden', + trafficLightPosition: { x: 20, y: 20 }, }); const launcherParams = '?window=featureFlags'; From 4c396516d140a96894e5bcef500ae0e93dbcf60a Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 15:17:13 +1100 Subject: [PATCH 6/9] simpler rendering what goose can do for you --- ui/desktop/src/components/Splash.tsx | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/ui/desktop/src/components/Splash.tsx b/ui/desktop/src/components/Splash.tsx index 036231ccb..c7505dc37 100644 --- a/ui/desktop/src/components/Splash.tsx +++ b/ui/desktop/src/components/Splash.tsx @@ -1,23 +1,10 @@ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import GooseSplashLogo from './GooseSplashLogo'; import SplashPills from './SplashPills'; import { featureFlags, type FeatureFlags } from '../featureFlags'; export default function Splash({ append }) { - const [flags, setFlags] = useState(featureFlags.getFlags()); - - // Update all feature flags when they change - useEffect(() => { - const updateInterval = setInterval(() => { - const currentFlags = featureFlags.getFlags(); - // Deep comparison to avoid unnecessary updates - if (JSON.stringify(currentFlags) !== JSON.stringify(flags)) { - setFlags(currentFlags); - } - }, 1000); - - return () => clearInterval(updateInterval); - }, [flags]); + const whatCanGooseDoText = featureFlags.getFlags().whatCanGooseDoText; return (
@@ -33,13 +20,13 @@ export default function Splash({ append }) { className="w-[312px] px-16 py-4 text-14 text-center text-splash-pills-text dark:text-splash-pills-text-dark whitespace-nowrap cursor-pointer bg-prev-goose-gradient dark:bg-dark-prev-goose-gradient text-prev-goose-text dark:text-prev-goose-text-dark rounded-[14px] inline-block hover:scale-[1.02] transition-all duration-150" onClick={async () => { const message = { - content: flags.whatCanGooseDoText, + content: whatCanGooseDoText, role: "user", }; await append(message); }} > - {flags.whatCanGooseDoText} + {whatCanGooseDoText}
From 138f43a67c376c20a06d747fa70f1a492e23ec46 Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 15:20:12 +1100 Subject: [PATCH 7/9] cleanup --- ui/desktop/src/components/Splash.tsx | 2 +- ui/desktop/src/featureFlags.ts | 6 ------ ui/desktop/src/preload.js | 6 ++---- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/ui/desktop/src/components/Splash.tsx b/ui/desktop/src/components/Splash.tsx index c7505dc37..1f94b9f94 100644 --- a/ui/desktop/src/components/Splash.tsx +++ b/ui/desktop/src/components/Splash.tsx @@ -37,4 +37,4 @@ export default function Splash({ append }) {
) -} \ No newline at end of file +} diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index 07dd2e99b..8e3d95f68 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -1,7 +1,6 @@ interface FeatureFlags { whatCanGooseDoText: string; expandedToolsByDefault: boolean; - // Add more feature flags here as needed } class FeatureFlagsManager { @@ -29,11 +28,6 @@ class FeatureFlagsManager { this.flags[typedKey] = savedFlags[typedKey]; } }); - - // Make feature flags available in the developer console - if (typeof window !== 'undefined') { - (window as any).featureFlags = this.flags; - } } private loadFlags(): Partial { diff --git a/ui/desktop/src/preload.js b/ui/desktop/src/preload.js index f0208d82f..3c98e5b33 100644 --- a/ui/desktop/src/preload.js +++ b/ui/desktop/src/preload.js @@ -20,14 +20,12 @@ contextBridge.exposeInMainWorld('electron', { reloadApp: () => ipcRenderer.send('reload-app'), selectFileOrDirectory: () => ipcRenderer.invoke('select-file-or-directory'), on: (channel, callback) => { - const validChannels = ['fatal-error', 'update-feature-flags']; - if (validChannels.includes(channel)) { + if (channel === 'fatal-error') { ipcRenderer.on(channel, callback); } }, off: (channel, callback) => { - const validChannels = ['fatal-error', 'update-feature-flags']; - if (validChannels.includes(channel)) { + if (channel === 'fatal-error') { ipcRenderer.removeListener(channel, callback); } } From 6ed0cec9d50233eea3d7720eb423ab965071a129 Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 15:25:11 +1100 Subject: [PATCH 8/9] remove extra file --- ui/desktop/src/windows/featureFlags.html | 11 ----------- ui/desktop/src/windows/featureFlags.tsx | 2 +- ui/desktop/vite.config.mts | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 ui/desktop/src/windows/featureFlags.html diff --git a/ui/desktop/src/windows/featureFlags.html b/ui/desktop/src/windows/featureFlags.html deleted file mode 100644 index c9f090361..000000000 --- a/ui/desktop/src/windows/featureFlags.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Feature Flags - - -
- - - \ No newline at end of file diff --git a/ui/desktop/src/windows/featureFlags.tsx b/ui/desktop/src/windows/featureFlags.tsx index 1f562db3c..19cafe999 100644 --- a/ui/desktop/src/windows/featureFlags.tsx +++ b/ui/desktop/src/windows/featureFlags.tsx @@ -83,7 +83,7 @@ export default function FeatureFlagsWindow() { function getFeatureFlagDescription(key: string): string { const descriptions: Record = { - whatCanGooseDoText: "Customize the placeholder text shown in the chat input field", + whatCanGooseDoText: "Customize the splash screen button text", expandedToolsByDefault: "Show tool outputs expanded by default instead of collapsed" }; return descriptions[key] || "No description available"; diff --git a/ui/desktop/vite.config.mts b/ui/desktop/vite.config.mts index 2ee3b19f2..fb6c807a1 100644 --- a/ui/desktop/vite.config.mts +++ b/ui/desktop/vite.config.mts @@ -10,7 +10,6 @@ export default defineConfig({ input: { main: resolve(__dirname, 'src/main.ts'), index: resolve(__dirname, 'index.html'), - featureFlags: resolve(__dirname, 'src/windows/featureFlags.html'), }, }, }, From b6a258d7f7202e1d6b1ebf7e88c203f1cee7e400 Mon Sep 17 00:00:00 2001 From: Jarrod Sibbison Date: Thu, 12 Dec 2024 15:29:01 +1100 Subject: [PATCH 9/9] reorganise --- ui/desktop/src/App.tsx | 2 +- .../featureFlagsWindow.ts => FeatureFlagsWindow.ts} | 0 .../featureFlags.tsx => components/FeatureFlags.tsx} | 6 +++--- ui/desktop/src/main.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename ui/desktop/src/{windows/featureFlagsWindow.ts => FeatureFlagsWindow.ts} (100%) rename ui/desktop/src/{windows/featureFlags.tsx => components/FeatureFlags.tsx} (96%) diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 5f4a7f948..23a23cb46 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import LauncherWindow from './LauncherWindow'; import ChatWindow from './ChatWindow'; import ErrorScreen from './components/ErrorScreen'; -import FeatureFlagsWindow from './windows/featureFlags'; +import FeatureFlagsWindow from './components/FeatureFlags'; export default function App() { const [fatalError, setFatalError] = useState(null); diff --git a/ui/desktop/src/windows/featureFlagsWindow.ts b/ui/desktop/src/FeatureFlagsWindow.ts similarity index 100% rename from ui/desktop/src/windows/featureFlagsWindow.ts rename to ui/desktop/src/FeatureFlagsWindow.ts diff --git a/ui/desktop/src/windows/featureFlags.tsx b/ui/desktop/src/components/FeatureFlags.tsx similarity index 96% rename from ui/desktop/src/windows/featureFlags.tsx rename to ui/desktop/src/components/FeatureFlags.tsx index 19cafe999..f1d0a18ae 100644 --- a/ui/desktop/src/windows/featureFlags.tsx +++ b/ui/desktop/src/components/FeatureFlags.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { featureFlags, type FeatureFlags } from '../featureFlags'; -import { Card } from '../components/ui/card'; -import { Input } from '../components/ui/input'; -import Box from '../components/ui/Box'; +import { Card } from './ui/card'; +import { Input } from './ui/input'; +import Box from './ui/Box'; export default function FeatureFlagsWindow() { const [flags, setFlags] = React.useState(featureFlags.getFlags()); diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 09d95cf6e..2d0e9e1dc 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -7,7 +7,7 @@ import started from "electron-squirrel-startup"; import log from './utils/logger'; import { exec } from 'child_process'; import { addRecentDir, loadRecentDirs } from './utils/recentDirs'; -import { createFeatureFlagsWindow } from './windows/featureFlagsWindow'; +import { createFeatureFlagsWindow } from './FeatureFlagsWindow'; // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (started) app.quit();