Create / edit recipe form unification and improvements (#4693)

This commit is contained in:
Zane
2025-10-05 09:00:59 -07:00
committed by GitHub
parent ebb3888ff1
commit f4d79404ee
55 changed files with 4486 additions and 3074 deletions
+31 -50
View File
@@ -45,7 +45,6 @@ import React, { createContext, useContext, useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import { SearchView } from './conversation/SearchView';
import { AgentHeader } from './AgentHeader';
import LayingEggLoader from './LayingEggLoader';
import LoadingGoose from './LoadingGoose';
import RecipeActivities from './recipes/RecipeActivities';
import PopularChatTopics from './PopularChatTopics';
@@ -57,6 +56,7 @@ import ChatInput from './ChatInput';
import { ScrollArea, ScrollAreaHandle } from './ui/scroll-area';
import { RecipeWarningModal } from './ui/RecipeWarningModal';
import ParameterInputModal from './ParameterInputModal';
import CreateRecipeFromSessionModal from './recipes/CreateRecipeFromSessionModal';
import { useChatEngine } from '../hooks/useChatEngine';
import { useRecipeManager } from '../hooks/useRecipeManager';
import { useFileDrop } from '../hooks/useFileDrop';
@@ -148,7 +148,7 @@ function BaseChatContent({
},
onMessageSent: () => {
// Mark that user has started using the recipe
if (recipeConfig) {
if (recipe) {
setHasStartedUsingRecipe(true);
}
},
@@ -156,28 +156,28 @@ function BaseChatContent({
// Use shared recipe manager
const {
recipeConfig,
recipe,
recipeParameters,
filteredParameters,
initialPrompt,
isGeneratingRecipe,
isParameterModalOpen,
setIsParameterModalOpen,
recipeParameters,
handleParameterSubmit,
handleAutoExecution,
recipeError,
setRecipeError,
isRecipeWarningModalOpen,
recipeAccepted,
handleRecipeAccept,
handleRecipeCancel,
hasSecurityWarnings,
} = useRecipeManager(chat, location.state?.recipeConfig);
isCreateRecipeModalOpen,
setIsCreateRecipeModalOpen,
handleRecipeCreated,
} = useRecipeManager(chat, location.state?.recipe);
// Reset recipe usage tracking when recipe changes
useEffect(() => {
const previousTitle = currentRecipeTitle;
const newTitle = recipeConfig?.title || null;
const newTitle = recipe?.title || null;
const hasRecipeChanged = newTitle !== currentRecipeTitle;
if (hasRecipeChanged) {
@@ -197,7 +197,7 @@ function BaseChatContent({
setHasStartedUsingRecipe(true);
}
}
}, [recipeConfig?.title, currentRecipeTitle, messages.length, setMessages]);
}, [recipe?.title, currentRecipeTitle, messages.length, setMessages]);
// Handle recipe auto-execution
useEffect(() => {
@@ -251,7 +251,7 @@ function BaseChatContent({
const combinedTextFromInput = customEvent.detail?.value || '';
// Mark that user has started using the recipe when they submit a message
if (recipeConfig && combinedTextFromInput.trim()) {
if (recipe && combinedTextFromInput.trim()) {
setHasStartedUsingRecipe(true);
}
@@ -268,7 +268,7 @@ function BaseChatContent({
// Wrapper for append that tracks recipe usage
const appendWithTracking = (text: string | Message) => {
// Mark that user has started using the recipe when they use append
if (recipeConfig) {
if (recipe) {
setHasStartedUsingRecipe(true);
}
append(text);
@@ -296,9 +296,6 @@ function BaseChatContent({
removeTopPadding={true}
{...customMainLayoutProps}
>
{/* Loader when generating recipe */}
{isGeneratingRecipe && <LayingEggLoader />}
{/* Custom header */}
{renderHeader && renderHeader()}
@@ -315,14 +312,12 @@ function BaseChatContent({
paddingY={0}
>
{/* Recipe agent header - sticky at top of chat container */}
{recipeConfig?.title && (
{recipe?.title && (
<div className="sticky top-0 z-10 bg-background-default px-0 -mx-6 mb-6 pt-6">
<AgentHeader
title={recipeConfig.title}
title={recipe.title}
profileInfo={
recipeConfig.profile
? `${recipeConfig.profile} - ${recipeConfig.mcps || 12} MCPs`
: undefined
recipe.profile ? `${recipe.profile} - ${recipe.mcps || 12} MCPs` : undefined
}
onChangeProfile={() => {
console.log('Change profile clicked');
@@ -336,14 +331,12 @@ function BaseChatContent({
{renderBeforeMessages && renderBeforeMessages()}
{/* Recipe Activities - always show when recipe is active and accepted */}
{recipeConfig && recipeAccepted && !suppressEmptyState && (
{recipe && recipeAccepted && !suppressEmptyState && (
<div className={hasStartedUsingRecipe ? 'mb-6' : ''}>
<RecipeActivities
append={(text: string) => appendWithTracking(text)}
activities={
Array.isArray(recipeConfig.activities) ? recipeConfig.activities : null
}
title={recipeConfig.title}
activities={Array.isArray(recipe.activities) ? recipe.activities : null}
title={recipe.title}
parameterValues={recipeParameters || {}}
/>
</div>
@@ -352,7 +345,7 @@ function BaseChatContent({
{/* Messages or Popular Topics */}
{
loadingChat ? null : filteredMessages.length > 0 ||
(recipeConfig && recipeAccepted && hasStartedUsingRecipe) ? (
(recipe && recipeAccepted && hasStartedUsingRecipe) ? (
<>
{disableSearch ? (
// Render messages without SearchView wrapper when search is disabled
@@ -436,7 +429,7 @@ function BaseChatContent({
<div className="block h-8" />
</>
) : !recipeConfig && showPopularTopics ? (
) : !recipe && showPopularTopics ? (
/* Show PopularChatTopics when no messages, no recipe, and showPopularTopics is true (Pair view) */
<PopularChatTopics append={(text: string) => append(text)} />
) : null /* Show nothing when messages.length === 0 && suppressEmptyState === true */
@@ -484,7 +477,7 @@ function BaseChatContent({
disableAnimation={disableAnimation}
sessionCosts={sessionCosts}
setIsGoosehintsModalOpen={setIsGoosehintsModalOpen}
recipeConfig={recipeConfig}
recipe={recipe}
recipeAccepted={recipeAccepted}
initialPrompt={initialPrompt}
toolCount={toolCount || 0}
@@ -501,9 +494,9 @@ function BaseChatContent({
onConfirm={handleRecipeAccept}
onCancel={handleRecipeCancel}
recipeDetails={{
title: recipeConfig?.title,
description: recipeConfig?.description,
instructions: recipeConfig?.instructions || undefined,
title: recipe?.title,
description: recipe?.description,
instructions: recipe?.instructions || undefined,
}}
hasSecurityWarnings={hasSecurityWarnings}
/>
@@ -517,25 +510,13 @@ function BaseChatContent({
/>
)}
{/* Recipe Error Modal */}
{recipeError && (
<div className="fixed inset-0 z-[300] flex items-center justify-center bg-black/50">
<div className="bg-background-default border border-borderSubtle rounded-lg p-6 w-96 max-w-[90vw]">
<h3 className="text-lg font-medium text-textProminent mb-4">Recipe Creation Failed</h3>
<p className="text-textStandard mb-6">{recipeError}</p>
<div className="flex justify-end">
<button
onClick={() => setRecipeError(null)}
className="px-4 py-2 bg-textProminent text-bgApp rounded-lg hover:bg-opacity-90 transition-colors"
>
OK
</button>
</div>
</div>
</div>
)}
{/* No modals needed for the new simplified context manager */}
{/* Create Recipe from Session Modal */}
<CreateRecipeFromSessionModal
isOpen={isCreateRecipeModalOpen}
onClose={() => setIsCreateRecipeModalOpen(false)}
sessionId={chat.sessionId}
onRecipeCreated={handleRecipeCreated}
/>
</div>
);
}