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
23 changes: 20 additions & 3 deletions ui/desktop/src/components/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,34 @@ export default function ChatInput({
setHasUserTyped(false);
}, [initialValue]); // Keep only initialValue as a dependency

// Track if we've already set the recipe prompt to avoid re-setting it
const hasSetRecipePromptRef = useRef(false);

// 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()) {
// If recipe is accepted and we have an initial prompt, and no messages yet, and we haven't set it before
if (
recipeAccepted &&
initialPrompt &&
messages.length === 0 &&
!hasSetRecipePromptRef.current
) {
setDisplayValue(initialPrompt);
setValue(initialPrompt);
hasSetRecipePromptRef.current = true;
setTimeout(() => {
textAreaRef.current?.focus();
}, 0);
}
}, [recipeAccepted, initialPrompt, messages.length, displayValue]);
// we don't need hasSetRecipePromptRef in the dependency array because it is a ref that persists across renders
}, [recipeAccepted, initialPrompt, messages.length]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we need hasSetRecipePromptRef in the deps here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no its not needed because its a ref object so it doesn't change only the .current property changes but changes to .current in refs don't trigger re-renders anyway. I added a comment for futuredev


// Reset the recipe prompt flag when the recipe changes or messages are added
useEffect(() => {
if (messages.length > 0 || !recipeAccepted || !initialPrompt) {
hasSetRecipePromptRef.current = false;
}
}, [recipeAccepted, initialPrompt, messages.length]);

// Draft functionality - load draft if no initial value or recipe
useEffect(() => {
Expand Down
14 changes: 1 addition & 13 deletions ui/desktop/src/hooks/useRecipeManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState, useRef } from 'react';
import { createRecipe, Recipe } from '../recipe';
import { Message, createUserMessage } from '../types/message';
import { updateSystemPromptWithParameters } from '../utils/providerUtils';
import { updateSystemPromptWithParameters, substituteParameters } from '../utils/providerUtils';
import { useChatContext } from '../contexts/ChatContext';

interface LocationState {
Expand Down Expand Up @@ -115,18 +115,6 @@ export const useRecipeManager = (messages: Message[], locationState?: LocationSt
setReadyForAutoUserPrompt(true);
}, []);

// Substitute parameters in prompt
const substituteParameters = (prompt: string, params: Record<string, string>): string => {
let substitutedPrompt = prompt;

for (const key in params) {
// Escape special characters in the key (parameter) and match optional whitespace
const regex = new RegExp(`{{\\s*${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*}}`, 'g');
substitutedPrompt = substitutedPrompt.replace(regex, params[key]);
}
return substitutedPrompt;
};

// 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 || recipeConfig?.isScheduledExecution) {
Expand Down
2 changes: 1 addition & 1 deletion ui/desktop/src/utils/providerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ There may be (but not always) some tools mentioned in the instructions which you
`;

// Helper function to substitute parameters in text
const substituteParameters = (text: string, params: Record<string, string>): string => {
export const substituteParameters = (text: string, params: Record<string, string>): string => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice deduping!

let substitutedText = text;

for (const key in params) {
Expand Down
Loading