From fdd6c8d63b79c5102ff48bd54baab531103cf092 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Fri, 24 Oct 2025 09:26:13 +0100 Subject: [PATCH] Allow folders in file picker and use them as search filters - Remove directory filtering from file picker - When folder selected, insert folder path into input (not as attachment) - Folder path becomes search query to filter files in that folder - Files still create attachments as before - User can navigate folder structure using @ mentions --- src/components/file-picker.tsx | 20 ++++++++------------ src/components/prompt-input.tsx | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/components/file-picker.tsx b/src/components/file-picker.tsx index f597c4be..5c9d8c5a 100644 --- a/src/components/file-picker.tsx +++ b/src/components/file-picker.tsx @@ -48,14 +48,12 @@ const FilePicker: Component = (props) => { console.log(`[FilePicker] Git files response received in ${elapsed}ms:`, gitResponse) if (gitResponse?.data && gitResponse.data.length > 0) { - const gitFiles: FileItem[] = gitResponse.data - .filter((file: any) => !file.path.endsWith("/")) - .map((file: any) => ({ - path: file.path, - added: file.added, - removed: file.removed, - isGitFile: true, - })) + const gitFiles: FileItem[] = gitResponse.data.map((file: any) => ({ + path: file.path, + added: file.added, + removed: file.removed, + isGitFile: true, + })) console.log(`[FilePicker] Cached ${gitFiles.length} git files`) setCachedGitFiles(gitFiles) } else { @@ -93,23 +91,21 @@ const FilePicker: Component = (props) => { console.log(`[FilePicker] Search response received in ${elapsed}ms:`, searchResponse) searchFiles = (searchResponse?.data || []) - .filter((path: string) => !path.endsWith("/")) .filter((path: string) => !gitFiles.some((gf) => gf.path === path)) .map((path: string) => ({ path, isGitFile: false, })) } else { - console.log(`[FilePicker] Empty query, fetching all files with wildcard`) + console.log(`[FilePicker] Empty query, fetching all files`) const searchResponse = await props.instanceClient.find.files({ - query: { query: "." }, + query: { query: "" }, }) const elapsed = Date.now() - startTime console.log(`[FilePicker] All files response received in ${elapsed}ms:`, searchResponse) searchFiles = (searchResponse?.data || []) - .filter((path: string) => !path.endsWith("/")) .filter((path: string) => !gitFiles.some((gf) => gf.path === path)) .map((path: string) => ({ path, diff --git a/src/components/prompt-input.tsx b/src/components/prompt-input.tsx index bbe51cea..9b1fac98 100644 --- a/src/components/prompt-input.tsx +++ b/src/components/prompt-input.tsx @@ -317,8 +317,36 @@ export default function PromptInput(props: PromptInputProps) { } function handleFileSelect(path: string) { + const isFolder = path.endsWith("/") const filename = path.split("/").pop() || path + if (isFolder) { + const currentPrompt = prompt() + const pos = atPosition() + const cursorPos = textareaRef?.selectionStart || 0 + + if (pos !== null) { + const before = currentPrompt.substring(0, pos + 1) + const after = currentPrompt.substring(cursorPos) + const folderPath = path.slice(0, -1) + const newPrompt = before + folderPath + after + setPrompt(newPrompt) + setFileSearchQuery(folderPath) + + setTimeout(() => { + if (textareaRef) { + const newCursorPos = pos + 1 + folderPath.length + textareaRef.setSelectionRange(newCursorPos, newCursorPos) + textareaRef.style.height = "auto" + textareaRef.style.height = Math.min(textareaRef.scrollHeight, 200) + "px" + textareaRef.focus() + } + }, 0) + } + + return + } + const existingAttachments = attachments() const alreadyAttached = existingAttachments.some((att) => att.source.type === "file" && att.source.path === path)