Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions ui/desktop/src/components/BaseChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ function BaseChatContent({
// Use shared recipe manager
const {
recipeConfig,
filteredParameters,
initialPrompt,
isGeneratingRecipe,
isParameterModalOpen,
Expand Down Expand Up @@ -546,9 +547,9 @@ function BaseChatContent({
/>

{/* Recipe Parameter Modal */}
{isParameterModalOpen && recipeConfig?.parameters && (
{isParameterModalOpen && filteredParameters.length > 0 && (
<ParameterInputModal
parameters={recipeConfig.parameters}
parameters={filteredParameters}
onSubmit={handleParameterSubmit}
onClose={() => setIsParameterModalOpen(false)}
/>
Expand Down
22 changes: 19 additions & 3 deletions ui/desktop/src/components/recipes/RecipesView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useMemo } from 'react';
import { listSavedRecipes, convertToLocaleDateString } from '../../recipe/recipeStorage';
import { FileText, Trash2, Bot, Calendar, AlertCircle } from 'lucide-react';
import { ScrollArea } from '../ui/scroll-area';
Expand All @@ -12,6 +12,7 @@ import { useEscapeKey } from '../../hooks/useEscapeKey';
import { deleteRecipe, RecipeManifestResponse } from '../../api';
import CreateRecipeForm, { CreateRecipeButton } from './CreateRecipeForm';
import ImportRecipeForm, { ImportRecipeButton } from './ImportRecipeForm';
import { filterValidUsedParameters } from '../../utils/providerUtils';

export default function RecipesView() {
const [savedRecipes, setSavedRecipes] = useState<RecipeManifestResponse[]>([]);
Expand Down Expand Up @@ -134,6 +135,21 @@ export default function RecipesView() {
}
};

const filteredPreviewParameters = useMemo(() => {
if (!selectedRecipe?.recipe.parameters) {
return [];
}

return filterValidUsedParameters(selectedRecipe.recipe.parameters, {
instructions: selectedRecipe.recipe.instructions || undefined,
prompt: selectedRecipe.recipe.prompt || undefined,
});
}, [
selectedRecipe?.recipe.parameters,
selectedRecipe?.recipe.instructions,
selectedRecipe?.recipe.prompt,
]);

// Render a recipe item
const RecipeItem = ({
recipeManifestResponse,
Expand Down Expand Up @@ -410,11 +426,11 @@ export default function RecipesView() {
</div>
)}

{selectedRecipe.recipe.parameters && selectedRecipe.recipe.parameters.length > 0 && (
{filteredPreviewParameters && filteredPreviewParameters.length > 0 && (
<div>
<h4 className="text-sm font-medium text-text-standard mb-2">Parameters</h4>
<div className="space-y-3">
{selectedRecipe.recipe.parameters.map((param, index) => (
{filteredPreviewParameters.map((param, index) => (
<div
key={index}
className="bg-background-muted border border-border-subtle p-3 rounded-lg"
Expand Down
5 changes: 4 additions & 1 deletion ui/desktop/src/components/recipes/ViewRecipeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ParameterInput from '../parameter/ParameterInput';
import { saveRecipe, generateRecipeFilename } from '../../recipe/recipeStorage';
import { toastSuccess, toastError } from '../../toasts';
import { Button } from '../ui/button';
import { filterValidUsedParameters } from '../../utils/providerUtils';

interface ViewRecipeModalProps {
isOpen: boolean;
Expand Down Expand Up @@ -124,6 +125,8 @@ export default function ViewRecipeModal({ isOpen, onClose, config }: ViewRecipeM
}
}, [instructions, prompt, parameters]);

// Filter parameters to only show valid ones that are actually used
const filteredParameters = filterValidUsedParameters(parameters, { instructions, prompt });
const getCurrentConfig = useCallback((): Recipe => {
// Transform the internal parameters state into the desired output format.
const formattedParameters = parameters.map((param) => {
Expand Down Expand Up @@ -459,7 +462,7 @@ export default function ViewRecipeModal({ isOpen, onClose, config }: ViewRecipeM
)}
</div>

{parameters.map((parameter: Parameter) => (
{filteredParameters.map((parameter: Parameter) => (
<ParameterInput
key={parameter.key}
parameter={parameter}
Expand Down
35 changes: 24 additions & 11 deletions ui/desktop/src/hooks/useRecipeManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useEffect, useMemo, useState, useRef } from 'react';
import { createRecipe, Recipe, scanRecipe } from '../recipe';
import { Message, createUserMessage } from '../types/message';
import { updateSystemPromptWithParameters, substituteParameters } from '../utils/providerUtils';
import {
updateSystemPromptWithParameters,
substituteParameters,
filterValidUsedParameters,
} from '../utils/providerUtils';
import { useChatContext } from '../contexts/ChatContext';
import { ChatType } from '../types/chat';

Expand Down Expand Up @@ -69,7 +73,21 @@ export const useRecipeManager = (chat: ChatType, recipeConfig?: Recipe | null) =
checkRecipeAcceptance();
}, [finalRecipeConfig]);

const requiresParameters = !!finalRecipeConfig?.parameters?.length;
// Filter parameters to only show valid ones that are actually used in the recipe
const filteredParameters = useMemo(() => {
if (!finalRecipeConfig?.parameters) {
return [];
}
return filterValidUsedParameters(finalRecipeConfig.parameters, {
prompt: finalRecipeConfig.prompt || undefined,
instructions: finalRecipeConfig.instructions || undefined,
});
}, [finalRecipeConfig]);

// Check if template variables are actually used in the recipe content
const requiresParameters = useMemo(() => {
return filteredParameters.length > 0;
}, [filteredParameters]);
const hasParameters = !!recipeParameters;
const hasMessages = messages.length > 0;
useEffect(() => {
Expand All @@ -89,15 +107,12 @@ export const useRecipeManager = (chat: ChatType, recipeConfig?: Recipe | null) =
return '';
}

const hasRequiredParams =
finalRecipeConfig.parameters && finalRecipeConfig.parameters.length > 0;

if (hasRequiredParams && recipeParameters) {
if (requiresParameters && recipeParameters) {
return substituteParameters(finalRecipeConfig.prompt, recipeParameters);
}

return finalRecipeConfig.prompt;
}, [finalRecipeConfig, recipeParameters, recipeAccepted]);
}, [finalRecipeConfig, recipeParameters, recipeAccepted, requiresParameters]);

const handleParameterSubmit = async (inputValues: Record<string, string>) => {
setRecipeParameters(inputValues);
Expand Down Expand Up @@ -138,13 +153,10 @@ export const useRecipeManager = (chat: ChatType, recipeConfig?: Recipe | null) =
isLoading: boolean,
onAutoExecute?: () => void
) => {
const hasRequiredParams =
finalRecipeConfig?.parameters && finalRecipeConfig.parameters.length > 0;

if (
finalRecipeConfig?.isScheduledExecution &&
finalRecipeConfig?.prompt &&
(!hasRequiredParams || recipeParameters) &&
(!requiresParameters || recipeParameters) &&
messages.length === 0 &&
!isLoading &&
readyForAutoUserPrompt &&
Expand Down Expand Up @@ -235,6 +247,7 @@ export const useRecipeManager = (chat: ChatType, recipeConfig?: Recipe | null) =

return {
recipeConfig: finalRecipeConfig,
filteredParameters,
initialPrompt,
isGeneratingRecipe,
isParameterModalOpen,
Expand Down
Loading
Loading