diff --git a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectory.svelte b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectory.svelte index f8069c93e..108cf1b19 100644 --- a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectory.svelte +++ b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormWorkingDirectory.svelte @@ -67,6 +67,20 @@ const pickerSupported = typeof window !== 'undefined' && typeof window.showDirectoryPicker === 'function'; + // When the server does not serve file_glob_search or the user disabled + // it, the picker still opens for manual entry but explains why search is + // unavailable instead of firing searches that would only fail. Browse is + // hidden too: it resolves the picked folder name through the same tool. + const fileSearchKey = $derived(toolsStore.getPermissionKey(BuiltInTool.FILE_GLOB_SEARCH)); + const fileSearchEnabled = $derived( + fileSearchKey !== null && toolsStore.isToolEnabled(fileSearchKey) + ); + const searchUnavailableMessage = $derived( + fileSearchKey === null + ? 'File search is unavailable on this server - type a full path and press Enter' + : 'File search is disabled - type a full path and press Enter, or enable "Search files" in Settings > Tools' + ); + let searchInputRef: HTMLInputElement | null = $state(null); let queryResults = $state([]); @@ -98,7 +112,7 @@ if (!isOpen) return; const q = query.trim(); nav.reset(-1); - if (q) { + if (q && fileSearchEnabled) { search.run(q); } else { search.cancel(); @@ -123,7 +137,7 @@ // children too, so path navigation does not require a trailing slash. const search = useDebouncedSearch({ debounceMs: SEARCH_DEBOUNCE_MS, - canRun: () => isOpen, + canRun: () => isOpen && fileSearchEnabled, getQuery: () => query.trim(), run: async (q, signal, isCurrent) => { const trimmed = q.trim(); @@ -340,7 +354,9 @@ class="w-full" /> - {#if query.trim() && (search.isSearching || queryResults.length > 0 || searchError)} + {#if !fileSearchEnabled} +
{searchUnavailableMessage}
+ {:else if query.trim() && (search.isSearching || queryResults.length > 0 || searchError)} {/if} - {#if pickerSupported} + {#if pickerSupported && fileSearchEnabled}