From 37de919db1a00cd7eba3e27f5d81cc7aea28972a Mon Sep 17 00:00:00 2001 From: Stijnus <72551117+Stijnus@users.noreply.github.com> Date: Sat, 3 May 2025 19:58:28 +0200 Subject: [PATCH] Add detection for unlocked files to allow AI to continue with modifications in the same chat session --- app/components/chat/Chat.client.tsx | 55 +++++++++++++++++++++++++- app/lib/hooks/useLockedFilesChecker.ts | 55 +++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/app/components/chat/Chat.client.tsx b/app/components/chat/Chat.client.tsx index e5bfd123..c4ca7fa1 100644 --- a/app/components/chat/Chat.client.tsx +++ b/app/components/chat/Chat.client.tsx @@ -311,8 +311,59 @@ export const ChatImpl = memo( return; } - // Check if the message is trying to modify locked files or folders - const { hasLockedItems, lockedFiles, lockedFolders } = checkForLockedItems(messageContent); + /* + * Check if the message is trying to modify locked files or folders + * Also check if previously locked files are now unlocked + */ + const { + hasLockedItems, + lockedFiles, + lockedFolders, + isRespondingToLockMessage, + hasUnlockedItems, + unlockedFiles, + unlockedFolders, + } = checkForLockedItems(messageContent, true); + + // Special case: User has unlocked files and is responding to a lock message + if (isRespondingToLockMessage && hasUnlockedItems) { + // Create a list of unlocked items for display + const unlockedItemsList = [ + ...unlockedFiles.map((f) => `File: ${f.path}`), + ...unlockedFolders.map((f) => `Folder: ${f.path}`), + ].join('\n- '); + + // Add a user message to the chat + const userMessage: Message = { + id: Date.now().toString(), + role: 'user', + content: messageContent, + }; + + // Add an assistant message acknowledging the unlocked files + const assistantMessage: Message = { + id: (Date.now() + 1).toString(), + role: 'assistant', + content: `I see you've unlocked the following items:\n\n- ${unlockedItemsList}\n\nI can now proceed with modifying these items. What would you like me to do with them?`, + }; + + // Add both messages to the chat + setMessages([...messages, userMessage, assistantMessage]); + + // Clear the input + setInput(''); + + // Show a success alert + workbenchStore.actionAlert.set({ + type: 'success', + title: 'Files/Folders Unlocked', + description: 'You have successfully unlocked files/folders', + content: 'The AI can now modify these items.', + isLockedFile: false, + }); + + return; + } // If we have locked items, we'll handle this specially if (hasLockedItems) { diff --git a/app/lib/hooks/useLockedFilesChecker.ts b/app/lib/hooks/useLockedFilesChecker.ts index ed27814a..69a5228e 100644 --- a/app/lib/hooks/useLockedFilesChecker.ts +++ b/app/lib/hooks/useLockedFilesChecker.ts @@ -157,16 +157,25 @@ export function useLockedFilesChecker() { folders: { path: string; lockMode: string }[]; }>({ files: [], folders: [] }); + // Keep track of previously locked items that might have been unlocked + const [previouslyLockedItems, setPreviouslyLockedItems] = useState<{ + files: { path: string; lockMode: string }[]; + folders: { path: string; lockMode: string }[]; + }>({ files: [], folders: [] }); + /** * Check if a prompt is trying to modify locked files or folders * @param prompt The user's prompt + * @param checkPreviouslyLocked Whether to check if previously locked items are now unlocked * @returns An object with the modified prompt and whether any locked items were found */ - const checkForLockedItems = (prompt: string) => { + const checkForLockedItems = (prompt: string, checkPreviouslyLocked = false) => { const potentialPaths = extractPotentialFilePaths(prompt); const currentChatId = getCurrentChatId(); const lockedFiles: { path: string; lockMode: string }[] = []; const lockedFolders: { path: string; lockMode: string }[] = []; + const unlockedFiles: { path: string }[] = []; + const unlockedFolders: { path: string }[] = []; // Check each potential path potentialPaths.forEach((path) => { @@ -193,8 +202,35 @@ export function useLockedFilesChecker() { } }); + // If we're checking previously locked items, check if any of them are now unlocked + if (checkPreviouslyLocked) { + previouslyLockedItems.files.forEach((file) => { + const fileCheck = isFileLocked(file.path, currentChatId); + + if (!fileCheck.locked) { + unlockedFiles.push({ path: file.path }); + logger.info(`Previously locked file is now unlocked: ${file.path}`); + } + }); + + previouslyLockedItems.folders.forEach((folder) => { + const folderCheck = isFolderLocked(folder.path, currentChatId); + + if (!folderCheck.locked) { + unlockedFolders.push({ path: folder.path }); + logger.info(`Previously locked folder is now unlocked: ${folder.path}`); + } + }); + } + + // Update the state with the current locked items setLockedItems({ files: lockedFiles, folders: lockedFolders }); + // If we found locked items, save them for future reference + if (lockedFiles.length > 0 || lockedFolders.length > 0) { + setPreviouslyLockedItems({ files: lockedFiles, folders: lockedFolders }); + } + // If we found locked items, modify the prompt to warn the AI let modifiedPrompt = prompt; @@ -233,16 +269,33 @@ export function useLockedFilesChecker() { }); } + // Check if the user is responding to a locked file message and has unlocked some files + const isRespondingToLockMessage = /unlock|unlocked|unlocking/i.test(prompt); + const hasUnlockedItems = unlockedFiles.length > 0 || unlockedFolders.length > 0; + return { modifiedPrompt, hasLockedItems: lockedFiles.length > 0 || lockedFolders.length > 0, lockedFiles, lockedFolders, + isRespondingToLockMessage, + hasUnlockedItems, + unlockedFiles, + unlockedFolders, }; }; + /** + * Reset the previously locked items state + */ + const resetPreviouslyLockedItems = () => { + setPreviouslyLockedItems({ files: [], folders: [] }); + }; + return { lockedItems, + previouslyLockedItems, checkForLockedItems, + resetPreviouslyLockedItems, }; }