diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 458814821757..a1d5abee7182 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -82,6 +82,8 @@ const PairRouteWrapper = ({ const setView = useMemo(() => createNavigationHandler(navigate), [navigate]); const routeState = (location.state as PairRouteState) || (window.history.state as PairRouteState) || {}; + const [resumeSessionId] = useState(routeState.resumeSessionId); + const [initialMessage] = useState(routeState.initialMessage); return ( ); }; @@ -121,23 +124,8 @@ const SchedulesRoute = () => { return navigate('/')} />; }; -const RecipesRoute = ({ resetChat }: { resetChat: () => void }) => { - const navigate = useNavigate(); - - return ( - { - // Navigate to pair view with the recipe configuration in state - resetChat(); - const stateData: PairRouteState = { - recipeConfig: recipe, - }; - navigate('/pair', { - state: stateData, - }); - }} - /> - ); +const RecipesRoute = () => { + return ; }; const RecipeEditorRoute = () => { @@ -378,11 +366,14 @@ export default function App() { const stateData: PairRouteState = { resumeSessionId: resumeSessionId || undefined, - recipeConfig: recipeFromAppConfig || undefined, }; (async () => { try { - await loadCurrentChat({ setAgentWaitingMessage, ...stateData }); + await loadCurrentChat({ + setAgentWaitingMessage, + recipeConfig: recipeFromAppConfig || undefined, + ...stateData, + }); } catch (e) { if (e instanceof NoProviderOrModelError) { // the onboarding flow will trigger @@ -474,69 +465,6 @@ export default function App() { }; }, []); - // Handle recipe decode events from main process - useEffect(() => { - const handleLoadRecipeDeeplink = (_event: IpcRendererEvent, ...args: unknown[]) => { - const recipeDeeplink = args[0] as string; - const scheduledJobId = args[1] as string | undefined; - - // Store the deeplink info in app config for processing - const config = window.electron.getConfig(); - config.recipeDeeplink = recipeDeeplink; - if (scheduledJobId) { - config.scheduledJobId = scheduledJobId; - } - - // Navigate to pair view to handle the recipe loading - if (window.location.hash !== '#/pair') { - window.location.hash = '#/pair'; - } - }; - - const handleRecipeDecoded = (_event: IpcRendererEvent, ...args: unknown[]) => { - const decodedRecipe = args[0] as Recipe; - - setChat((prevChat) => ({ - ...prevChat, - recipeConfig: decodedRecipe, - title: decodedRecipe.title || 'Recipe Chat', - messages: [], // Start fresh for recipe - messageHistoryIndex: 0, - })); - - const stateData: PairRouteState = { - recipeConfig: decodedRecipe, - }; - - resetChat(); - - // Navigate to pair view if not already there - if (window.location.hash !== '#/pair') { - window.location.hash = '#/pair'; - } - window.history.replaceState(stateData, '', '#/pair'); - }; - - const handleRecipeDecodeError = (_event: IpcRendererEvent, ...args: unknown[]) => { - const errorMessage = args[0] as string; - console.error('[App] Recipe decode error:', errorMessage); - - // Show error to user - you could add a toast notification here - // For now, just log the error and navigate to recipes page - window.location.hash = '#/recipes'; - }; - - window.electron.on('load-recipe-deeplink', handleLoadRecipeDeeplink); - window.electron.on('recipe-decoded', handleRecipeDecoded); - window.electron.on('recipe-decode-error', handleRecipeDecodeError); - - return () => { - window.electron.off('load-recipe-deeplink', handleLoadRecipeDeeplink); - window.electron.off('recipe-decoded', handleRecipeDecoded); - window.electron.off('recipe-decode-error', handleRecipeDecodeError); - }; - }, [setChat, resetChat]); - useEffect(() => { console.log('Setting up keyboard shortcuts'); const handleKeyDown = (event: KeyboardEvent) => { @@ -735,7 +663,7 @@ export default function App() { } /> } /> } /> - } /> + } /> } /> {/* Recipe agent header - sticky at top of chat container */} - {recipeConfig?.title && !recipeResetOverride && ( + {recipeConfig?.title && (
@@ -497,7 +501,7 @@ function BaseChatContent({ /> {/* Recipe Parameter Modal */} - {isParameterModalOpen && recipeConfig?.parameters && !recipeResetOverride && ( + {isParameterModalOpen && recipeConfig?.parameters && (

Recipe Creation Failed

diff --git a/ui/desktop/src/components/RecipesView.tsx b/ui/desktop/src/components/RecipesView.tsx index 553914711b4a..abf60be7b06e 100644 --- a/ui/desktop/src/components/RecipesView.tsx +++ b/ui/desktop/src/components/RecipesView.tsx @@ -16,12 +16,7 @@ import { toastSuccess, toastError } from '../toasts'; import { useEscapeKey } from '../hooks/useEscapeKey'; import { deleteRecipe, RecipeManifestResponse } from '../api'; -interface RecipesViewProps { - onLoadRecipe?: (recipe: Recipe) => void; -} - -// @ts-expect-error until we make onLoadRecipe work for loading recipes in the same window -export default function RecipesView({ _onLoadRecipe }: RecipesViewProps = {}) { +export default function RecipesView() { const [savedRecipes, setSavedRecipes] = useState([]); const [loading, setLoading] = useState(true); const [showSkeleton, setShowSkeleton] = useState(true); diff --git a/ui/desktop/src/components/pair.tsx b/ui/desktop/src/components/pair.tsx index bcc3c0e37285..6a60fec1a732 100644 --- a/ui/desktop/src/components/pair.tsx +++ b/ui/desktop/src/components/pair.tsx @@ -9,14 +9,23 @@ import 'react-toastify/dist/ReactToastify.css'; import { cn } from '../utils'; import { ChatType } from '../types/chat'; -import { Recipe } from '../recipe'; export interface PairRouteState { resumeSessionId?: string; - recipeConfig?: Recipe; initialMessage?: string; } +interface PairProps { + chat: ChatType; + setChat: (chat: ChatType) => void; + setView: (view: View, viewOptions?: ViewOptions) => void; + setIsGoosehintsModalOpen: (isOpen: boolean) => void; + setFatalError: (value: ((prevState: string | null) => string | null) | string | null) => void; + setAgentWaitingMessage: (msg: string | null) => void; + agentState: AgentState; + loadCurrentChat: (context: InitializationContext) => Promise; +} + export default function Pair({ chat, setChat, @@ -26,25 +35,15 @@ export default function Pair({ setAgentWaitingMessage, agentState, loadCurrentChat, - routeState, -}: { - chat: ChatType; - setChat: (chat: ChatType) => void; - setView: (view: View, viewOptions?: ViewOptions) => void; - setIsGoosehintsModalOpen: (isOpen: boolean) => void; - setFatalError: (value: ((prevState: string | null) => string | null) | string | null) => void; - setAgentWaitingMessage: (msg: string | null) => void; - agentState: AgentState; - loadCurrentChat: (context: InitializationContext) => Promise; - routeState: PairRouteState; -}) { + resumeSessionId, + initialMessage, +}: PairProps & PairRouteState) { const isMobile = useIsMobile(); const { state: sidebarState } = useSidebar(); const [hasProcessedInitialInput, setHasProcessedInitialInput] = useState(false); const [shouldAutoSubmit, setShouldAutoSubmit] = useState(false); const [messageToSubmit, setMessageToSubmit] = useState(null); const [isTransitioningFromHub, setIsTransitioningFromHub] = useState(false); - const [recipeResetOverride, setRecipeResetOverride] = useState(false); const [loadingChat, setLoadingChat] = useState(false); useEffect(() => { @@ -52,12 +51,9 @@ export default function Pair({ setLoadingChat(true); try { const chat = await loadCurrentChat({ - resumeSessionId: routeState.resumeSessionId, + resumeSessionId: resumeSessionId, setAgentWaitingMessage, }); - if (!chat.recipeConfig && agentState === 'initialized') { - setRecipeResetOverride(true); - } setChat(chat); } catch (error) { console.log(error); @@ -73,26 +69,21 @@ export default function Pair({ setFatalError, setAgentWaitingMessage, loadCurrentChat, - routeState.resumeSessionId, - routeState.recipeConfig, + resumeSessionId, ]); // Followed by sending the initialMessage if we have one. This will happen // only once, unless we reset the chat in step one. useEffect(() => { - if ( - agentState !== AgentState.INITIALIZED || - !routeState.initialMessage || - hasProcessedInitialInput - ) { + if (agentState !== AgentState.INITIALIZED || !initialMessage || hasProcessedInitialInput) { return; } setIsTransitioningFromHub(true); setHasProcessedInitialInput(true); - setMessageToSubmit(routeState.initialMessage); + setMessageToSubmit(initialMessage); setShouldAutoSubmit(true); - }, [agentState, routeState.initialMessage, hasProcessedInitialInput]); + }, [agentState, initialMessage, hasProcessedInitialInput]); useEffect(() => { if (agentState === AgentState.NO_PROVIDER) { @@ -111,10 +102,7 @@ export default function Pair({ }; const recipePrompt = - agentState === 'initialized' && - !recipeResetOverride && - chat.messages.length === 0 && - recipeInitialPrompt; + agentState === 'initialized' && chat.messages.length === 0 && recipeInitialPrompt; const initialValue = messageToSubmit || recipePrompt || undefined; @@ -136,7 +124,6 @@ export default function Pair({ contentClassName={cn('pr-1 pb-10', (isMobile || sidebarState === 'collapsed') && 'pt-11')} // Use dynamic content class with mobile margin and sidebar state showPopularTopics={!isTransitioningFromHub} // Don't show popular topics while transitioning from Hub suppressEmptyState={isTransitioningFromHub} // Suppress all empty state content while transitioning from Hub - recipeResetOverride={recipeResetOverride} /> ); } diff --git a/ui/desktop/src/hooks/useAgent.ts b/ui/desktop/src/hooks/useAgent.ts index 511cb0b00115..3467d8887cee 100644 --- a/ui/desktop/src/hooks/useAgent.ts +++ b/ui/desktop/src/hooks/useAgent.ts @@ -134,12 +134,10 @@ export function useAgent(): UseAgentReturn { } agentWaitingMessage('Extensions are loading'); - console.log(`calling initializeSystem with sessionId: ${agentSessionInfo.session_id}`); await initializeSystem(agentSessionInfo.session_id, provider as string, model as string, { getExtensions, addExtension, }); - console.log('init system done!!'); if (COST_TRACKING_ENABLED) { try { @@ -194,7 +192,6 @@ const handleConfigRecovery = async () => { const shouldMigrateExtensions = !configVersion || parseInt(configVersion, 10) < 3; if (shouldMigrateExtensions) { - console.log('Performing extension migration...'); try { await backupConfig({ throwOnError: true }); await initConfig(); @@ -203,12 +200,10 @@ const handleConfigRecovery = async () => { } } - console.log('Attempting config recovery...'); try { await validateConfig({ throwOnError: true }); await readAllConfig({ throwOnError: true }); } catch { - console.log('Config validation failed, attempting recovery...'); try { await recoverConfig({ throwOnError: true }); await readAllConfig({ throwOnError: true }); diff --git a/ui/desktop/src/hooks/useRecipeManager.ts b/ui/desktop/src/hooks/useRecipeManager.ts index db8f025ac036..cea942b13918 100644 --- a/ui/desktop/src/hooks/useRecipeManager.ts +++ b/ui/desktop/src/hooks/useRecipeManager.ts @@ -73,8 +73,6 @@ export const useRecipeManager = (chat: ChatType, recipeConfig?: Recipe | null) = const hasParameters = !!recipeParameters; const hasMessages = messages.length > 0; useEffect(() => { - // If we have parameters and they haven't been set yet, open the modal. - console.log('should open modal', requiresParameters, hasParameters, recipeAccepted); if (requiresParameters && recipeAccepted) { if (!hasParameters && !hasMessages) { setIsParameterModalOpen(true);