@@ -43,10 +43,12 @@ import { createPortal } from 'react-dom'
4343import { supportsAtomicBrowserPanelOcclusion } from '@/lib/browser-agent/transport'
4444import { isChatEnabled } from '@/lib/core/config/env-flags'
4545import { MothershipHandoffStorage } from '@/lib/core/utils/browser-storage'
46+ import { getFolderPathNames } from '@/lib/folders/tree'
4647import { sendMothershipMessage } from '@/lib/mothership/events'
4748import { captureEvent } from '@/lib/posthog/client'
4849import { toSearchToken } from '@/lib/search/tokens'
4950import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
51+ import { parseWorkspaceFileFolderDisplayPath } from '@/lib/workspace-files/folder-display-path'
5052import { useInvokeGlobalCommand } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
5153import {
5254 CommandFadedList ,
@@ -86,8 +88,13 @@ import {
8688 CMDK_SECTION_GAP_CLASS ,
8789} from '@/app/workspace/[workspaceId]/w/components/sidebar/constants'
8890import { SIDEBAR_SCROLL_EVENT } from '@/app/workspace/[workspaceId]/w/components/sidebar/sidebar'
91+ import { useFolderMap } from '@/hooks/queries/folders'
92+ import { useKnowledgeBasesQuery } from '@/hooks/queries/kb/knowledge'
93+ import { useTablesList } from '@/hooks/queries/tables'
94+ import { useWorkspaceFiles } from '@/hooks/queries/workspace-files'
8995import { usePermissionConfig } from '@/hooks/use-permission-config'
9096import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
97+ import type { WorkflowFolder } from '@/stores/folders/types'
9198import { useSearchModalStore } from '@/stores/modals/search/store'
9299import type { SearchBlockItem , SearchToolOperationItem } from '@/stores/modals/search/types'
93100
@@ -101,6 +108,9 @@ const logger = createLogger('SearchModal')
101108export const MAX_BROWSE_RESULTS = Number . POSITIVE_INFINITY
102109const MAX_SEARCH_RESULTS = 50
103110
111+ /** Stable empty default so a pending folder map does not remount the memos below. */
112+ const EMPTY_FOLDER_MAP : Record < string , WorkflowFolder > = { }
113+
104114export type { SearchModalProps } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/utils'
105115
106116type SearchModalContentProps = Omit < SearchModalProps , 'open' >
@@ -121,9 +131,6 @@ function SearchModalContent({
121131 workflows = [ ] ,
122132 workspaces = [ ] ,
123133 chats = [ ] ,
124- tables = [ ] ,
125- files = [ ] ,
126- knowledgeBases = [ ] ,
127134 logs = [ ] ,
128135 integrations = [ ] ,
129136 connectedAccounts = [ ] ,
@@ -157,6 +164,83 @@ function SearchModalContent({
157164
158165 const { blocks, tools, triggers, toolOperations } = useSearchModalStore ( ( state ) => state . data )
159166
167+ /**
168+ * Read here rather than passed down from the sidebar. This component mounts only while the
169+ * palette is open, so these workspace-wide lists are fetched — and registered in the query
170+ * cache — only then. The sidebar renders on every workspace route, so holding them there put
171+ * three lists and two folder maps in the cache on routes that never display them, and a
172+ * registered key also blocks a page from seeding it during the server render.
173+ */
174+ const { data : fetchedTables = [ ] } = useTablesList ( workspaceId , 'active' , {
175+ enabled : ! permissionConfig . hideTablesTab ,
176+ } )
177+ const { data : fetchedFiles = [ ] } = useWorkspaceFiles ( workspaceId , 'active' , {
178+ enabled : ! permissionConfig . hideFilesTab ,
179+ } )
180+ const { data : fetchedKnowledgeBases = [ ] } = useKnowledgeBasesQuery ( workspaceId , {
181+ enabled : ! permissionConfig . hideKnowledgeBaseTab ,
182+ } )
183+ const { data : tableFolderMap = EMPTY_FOLDER_MAP } = useFolderMap (
184+ permissionConfig . hideTablesTab ? undefined : workspaceId ,
185+ 'table'
186+ )
187+ const { data : knowledgeBaseFolderMap = EMPTY_FOLDER_MAP } = useFolderMap (
188+ permissionConfig . hideKnowledgeBaseTab ? undefined : workspaceId ,
189+ 'knowledge_base'
190+ )
191+
192+ /**
193+ * The hidden-tab checks are repeated here, not left to `enabled`. A disabled query still
194+ * returns whatever is already cached — another surface may have filled it, or the permission
195+ * config may have flipped after it did — so gating only the fetch would let the palette list
196+ * entities a permission group hides.
197+ */
198+ const tables = useMemo (
199+ ( ) =>
200+ permissionConfig . hideTablesTab
201+ ? [ ]
202+ : fetchedTables . map ( ( t ) => ( {
203+ id : t . id ,
204+ name : t . name ,
205+ href : `/workspace/${ workspaceId } /tables/${ t . id } ` ,
206+ folderPath : getFolderPathNames ( tableFolderMap , t . folderId ) ,
207+ } ) ) ,
208+ [ fetchedTables , tableFolderMap , workspaceId , permissionConfig . hideTablesTab ]
209+ )
210+
211+ const files = useMemo (
212+ ( ) =>
213+ permissionConfig . hideFilesTab
214+ ? [ ]
215+ : fetchedFiles . map ( ( f ) => ( {
216+ id : f . id ,
217+ name : f . name ,
218+ href : `/workspace/${ workspaceId } /files/${ f . id } ` ,
219+ folderPath : f . folderPath
220+ ? parseWorkspaceFileFolderDisplayPath ( f . folderPath )
221+ : undefined ,
222+ } ) ) ,
223+ [ fetchedFiles , workspaceId , permissionConfig . hideFilesTab ]
224+ )
225+
226+ const knowledgeBases = useMemo (
227+ ( ) =>
228+ permissionConfig . hideKnowledgeBaseTab
229+ ? [ ]
230+ : fetchedKnowledgeBases . map ( ( kb ) => ( {
231+ id : kb . id ,
232+ name : kb . name ,
233+ href : `/workspace/${ workspaceId } /knowledge/${ kb . id } ` ,
234+ folderPath : getFolderPathNames ( knowledgeBaseFolderMap , kb . folderId ) ,
235+ } ) ) ,
236+ [
237+ fetchedKnowledgeBases ,
238+ knowledgeBaseFolderMap ,
239+ workspaceId ,
240+ permissionConfig . hideKnowledgeBaseTab ,
241+ ]
242+ )
243+
160244 const openHelpModal = useCallback ( ( ) => {
161245 window . dispatchEvent ( new CustomEvent ( 'open-help-modal' ) )
162246 } , [ ] )
0 commit comments