From 1417ed61fdec07a9f0fdc41f98f26dcb9f237f3b Mon Sep 17 00:00:00 2001 From: Zane Staggs Date: Thu, 24 Jul 2025 14:01:26 -0700 Subject: [PATCH 1/2] fix recipe initial prompt not populating after accepting recipe --- ui/desktop/src/components/BaseChat.tsx | 17 ++++++++++++++++- ui/desktop/src/components/ChatInput.tsx | 16 ++++++++++++++++ ui/desktop/src/components/pair.tsx | 18 +----------------- ui/desktop/src/hooks/useRecipeManager.ts | 14 ++++++-------- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/ui/desktop/src/components/BaseChat.tsx b/ui/desktop/src/components/BaseChat.tsx index 9897c0f49953..7f5d6275638c 100644 --- a/ui/desktop/src/components/BaseChat.tsx +++ b/ui/desktop/src/components/BaseChat.tsx @@ -61,6 +61,7 @@ import { MainPanelLayout } from './Layout/MainPanelLayout'; import ChatInput from './ChatInput'; import { ScrollArea, ScrollAreaHandle } from './ui/scroll-area'; import { RecipeWarningModal } from './ui/RecipeWarningModal'; +import ParameterInputModal from './ParameterInputModal'; import { useChatEngine } from '../hooks/useChatEngine'; import { useRecipeManager } from '../hooks/useRecipeManager'; import { useSessionContinuation } from '../hooks/useSessionContinuation'; @@ -188,6 +189,9 @@ function BaseChatContent({ recipeConfig, initialPrompt, isGeneratingRecipe, + isParameterModalOpen, + setIsParameterModalOpen, + handleParameterSubmit, handleAutoExecution, recipeError, setRecipeError, @@ -520,7 +524,7 @@ function BaseChatContent({ chatState={chatState} onStop={onStopGoose} commandHistory={commandHistory} - initialValue={_input || (messages.length === 0 ? initialPrompt : '')} + initialValue={_input || ''} setView={setView} numTokens={sessionTokenCount} inputTokens={sessionInputTokens || localInputTokens} @@ -533,6 +537,8 @@ function BaseChatContent({ sessionCosts={sessionCosts} setIsGoosehintsModalOpen={setIsGoosehintsModalOpen} recipeConfig={recipeConfig} + recipeAccepted={recipeAccepted} + initialPrompt={initialPrompt} {...customChatInputProps} /> @@ -560,6 +566,15 @@ function BaseChatContent({ }} /> + {/* Recipe Parameter Modal */} + {isParameterModalOpen && recipeConfig?.parameters && ( + setIsParameterModalOpen(false)} + /> + )} + {/* Recipe Error Modal */} {recipeError && (
diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index 92b832d0bbed..ddaf2759e4bf 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -75,6 +75,8 @@ interface ChatInputProps { setIsGoosehintsModalOpen?: (isOpen: boolean) => void; disableAnimation?: boolean; recipeConfig?: Recipe | null; + recipeAccepted?: boolean; + initialPrompt?: string; } export default function ChatInput({ @@ -95,6 +97,8 @@ export default function ChatInput({ sessionCosts, setIsGoosehintsModalOpen, recipeConfig, + recipeAccepted, + initialPrompt, }: ChatInputProps) { const [_value, setValue] = useState(initialValue); const [displayValue, setDisplayValue] = useState(initialValue); // For immediate visual feedback @@ -200,6 +204,18 @@ export default function ChatInput({ setHasUserTyped(false); }, [initialValue]); // Keep only initialValue as a dependency + // Handle recipe prompt updates + useEffect(() => { + // If recipe is accepted and we have an initial prompt, and no messages yet, set the prompt + if (recipeAccepted && initialPrompt && messages.length === 0 && !displayValue.trim()) { + setDisplayValue(initialPrompt); + setValue(initialPrompt); + setTimeout(() => { + textAreaRef.current?.focus(); + }, 0); + } + }, [recipeAccepted, initialPrompt, messages.length, displayValue]); + // Draft functionality - load draft if no initial value or recipe useEffect(() => { // Reset draft loaded flag when context changes diff --git a/ui/desktop/src/components/pair.tsx b/ui/desktop/src/components/pair.tsx index 00593ef9386a..ae068f46ba04 100644 --- a/ui/desktop/src/components/pair.tsx +++ b/ui/desktop/src/components/pair.tsx @@ -28,7 +28,6 @@ import { useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; import { type View, ViewOptions } from '../App'; import BaseChat from './BaseChat'; -import ParameterInputModal from './ParameterInputModal'; import { useRecipeManager } from '../hooks/useRecipeManager'; import { useIsMobile } from '../hooks/use-mobile'; import { useSidebar } from './ui/sidebar'; @@ -57,13 +56,7 @@ export default function Pair({ const [isTransitioningFromHub, setIsTransitioningFromHub] = useState(false); // Get recipe configuration and parameter handling - const { - recipeConfig, - initialPrompt: recipeInitialPrompt, - isParameterModalOpen, - setIsParameterModalOpen, - handleParameterSubmit, - } = useRecipeManager(chat.messages, location.state); + const { initialPrompt: recipeInitialPrompt } = useRecipeManager(chat.messages, location.state); // Handle recipe loading from recipes view - reset chat if needed useEffect(() => { @@ -196,15 +189,6 @@ export default function Pair({ showPopularTopics={!isTransitioningFromHub} // Don't show popular topics while transitioning from Hub suppressEmptyState={isTransitioningFromHub} // Suppress all empty state content while transitioning from Hub /> - - {/* Recipe Parameter Modal */} - {isParameterModalOpen && recipeConfig?.parameters && ( - setIsParameterModalOpen(false)} - /> - )} ); } diff --git a/ui/desktop/src/hooks/useRecipeManager.ts b/ui/desktop/src/hooks/useRecipeManager.ts index 6391e3e5cf6d..eb86d01d8968 100644 --- a/ui/desktop/src/hooks/useRecipeManager.ts +++ b/ui/desktop/src/hooks/useRecipeManager.ts @@ -129,7 +129,9 @@ export const useRecipeManager = (messages: Message[], locationState?: LocationSt // Get the recipe's initial prompt (always return the actual prompt, don't modify based on conversation state) const initialPrompt = useMemo(() => { - if (!recipeConfig?.prompt || !recipeAccepted) return ''; + if (!recipeConfig?.prompt || !recipeAccepted) { + return ''; + } const hasRequiredParams = recipeConfig.parameters && recipeConfig.parameters.length > 0; @@ -138,13 +140,9 @@ export const useRecipeManager = (messages: Message[], locationState?: LocationSt return substituteParameters(recipeConfig.prompt, recipeParameters); } - // If there are no parameters, return the original prompt. - if (!hasRequiredParams) { - return recipeConfig.prompt; - } - - // Otherwise, we are waiting for parameters, so the input should be empty. - return ''; + // Always return the original prompt, whether it has parameters or not + // The user should see the prompt with parameter placeholders before filling them in + return recipeConfig.prompt; }, [recipeConfig, recipeParameters, recipeAccepted]); // Handle parameter submission From e301a3374e8ce29b959ee95d7750c435b44ec134 Mon Sep 17 00:00:00 2001 From: Zane Staggs Date: Thu, 24 Jul 2025 14:03:40 -0700 Subject: [PATCH 2/2] update title of view recipe in bottom bar to match the dialog --- .../components/settings/models/bottom_bar/ModelsBottomBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/desktop/src/components/settings/models/bottom_bar/ModelsBottomBar.tsx b/ui/desktop/src/components/settings/models/bottom_bar/ModelsBottomBar.tsx index 120ab68bb542..bd983270a544 100644 --- a/ui/desktop/src/components/settings/models/bottom_bar/ModelsBottomBar.tsx +++ b/ui/desktop/src/components/settings/models/bottom_bar/ModelsBottomBar.tsx @@ -256,7 +256,7 @@ export default function ModelsBottomBar({ <> - View Recipe + View/Edit Recipe