@@ -75,10 +75,8 @@ interface AvailableItemsByType {
7575}
7676
7777/**
78- * Folder hierarchies that exist purely to structure the browse menus. Unlike
79- * workflow (`folder`) and workspace-file (`filefolder`) folders these are not
80- * attachable resources, so they stay out of `groups` — which also feeds the
81- * flat search results, where a non-attachable row would be a dead end.
78+ * Table and knowledge-base folder hierarchies. Chat also offers these as folder
79+ * mentions, while the resource tab picker uses them only for navigation.
8280 */
8381interface StructureFolders {
8482 table : AvailableItem [ ]
@@ -97,6 +95,8 @@ interface AvailableResources {
9795}
9896
9997interface UseAvailableResourcesOptions {
98+ /** Chat can attach every folder family, so these lists also gate mention hydration. */
99+ includeFolderMentions ?: boolean
100100 /**
101101 * Skips the underlying list queries and the group construction they feed
102102 * while `false`, returning a stable empty result. Menus pass their own open
@@ -171,16 +171,17 @@ export function useAvailableResources(
171171 { enabled }
172172 )
173173 const { data : folders , isPending : foldersPending } = useFolders ( workspaceId , { enabled } )
174- // Folder lists exist only to shape their family's submenu, so they skip the
175- // fetch entirely when that family is excluded.
176- const { data : tableFolders } = useFolders ( workspaceId , {
174+ const { data : tableFolders , isPending : tableFoldersPending } = useFolders ( workspaceId , {
177175 enabled : enabled && ! excludeTypes ?. includes ( 'table' ) ,
178176 resourceType : 'table' ,
179177 } )
180- const { data : knowledgeBaseFolders } = useFolders ( workspaceId , {
181- enabled : enabled && ! excludeTypes ?. includes ( 'knowledgebase' ) ,
182- resourceType : 'knowledge_base' ,
183- } )
178+ const { data : knowledgeBaseFolders , isPending : knowledgeBaseFoldersPending } = useFolders (
179+ workspaceId ,
180+ {
181+ enabled : enabled && ! excludeTypes ?. includes ( 'knowledgebase' ) ,
182+ resourceType : 'knowledge_base' ,
183+ }
184+ )
184185 const { data : fileFolders , isPending : fileFoldersPending } = useWorkspaceFileFolders (
185186 workspaceId ,
186187 'active' ,
@@ -199,10 +200,8 @@ export function useAvailableResources(
199200 * settles to "not hydrating" — an errored query must not block the caller
200201 * forever.
201202 *
202- * Only the lists feeding `groups` count. The table and knowledge-base folder
203- * lists shape submenus but never add candidates, so gating on them would
204- * swallow an `@`-mention Enter behind two round-trips that cannot change the
205- * answer.
203+ * Chat includes table and knowledge-base folders as candidates. Its Enter
204+ * handling must wait for those lists too, or an unresolved mention can submit.
206205 */
207206 const isHydrating =
208207 enabled &&
@@ -211,6 +210,9 @@ export function useAvailableResources(
211210 filesPending ||
212211 knowledgeBasesPending ||
213212 foldersPending ||
213+ ( options ?. includeFolderMentions &&
214+ ( ( ! excludeTypes ?. includes ( 'table' ) && tableFoldersPending ) ||
215+ ( ! excludeTypes ?. includes ( 'knowledgebase' ) && knowledgeBaseFoldersPending ) ) ) ||
214216 fileFoldersPending ||
215217 tasksPending ||
216218 logsPending )
@@ -371,9 +373,7 @@ interface ResourceFolderTreeItemsProps {
371373 /** Resource type of the leaf items. */
372374 type : MothershipResourceType
373375 /**
374- * Set when the folder is itself an attachable resource (workspace files): the
375- * folder is then offered as the first entry of its own submenu. Omitted for
376- * folders that only provide structure (workflows, tables, knowledge bases).
376+ * Offers the folder itself as the first entry of its submenu when selectable.
377377 */
378378 folderType ?: MothershipResourceType
379379 onSelect : ( resource : MothershipResource ) => void
@@ -429,10 +429,6 @@ export function ResourceFolderTreeItems({
429429interface FolderedSectionSpec {
430430 /** Leaf resource type — also supplies the submenu's label and icon. */
431431 type : MothershipResourceType
432- /**
433- * Where this family's folders come from: another entry in `groups` when the
434- * folders are attachable resources, or `structureFolders` when they are not.
435- */
436432 folders :
437433 | { kind : 'group' ; type : MothershipResourceType }
438434 | { kind : 'structure' ; key : keyof StructureFolders }
@@ -483,22 +479,25 @@ export interface ResourceTreeSection {
483479export function useResourceTreeSections ( {
484480 groups,
485481 structureFolders,
486- } : Pick < AvailableResources , 'groups' | 'structureFolders' > ) : ResourceTreeSection [ ] {
482+ selectFolders = false ,
483+ } : Pick < AvailableResources , 'groups' | 'structureFolders' > & {
484+ selectFolders ?: boolean
485+ } ) : ResourceTreeSection [ ] {
487486 return useMemo ( ( ) => {
488487 const itemsOf = ( type : MothershipResourceType ) =>
489488 groups . find ( ( group ) => group . type === type ) ?. items ?? [ ]
490489 return FOLDERED_SECTION_SPECS . map ( ( spec ) => ( {
491490 type : spec . type ,
492- folderType : spec . folderType ,
491+ folderType : spec . folderType ?? ( selectFolders ? 'folder' : undefined ) ,
493492 nodes : buildResourceFolderTree (
494493 itemsOf ( spec . type ) ,
495494 spec . folders . kind === 'group'
496495 ? itemsOf ( spec . folders . type )
497496 : structureFolders [ spec . folders . key ] ,
498- { orderBySortOrder : spec . orderBySortOrder , pruneEmpty : ! spec . folderType }
497+ { orderBySortOrder : spec . orderBySortOrder , pruneEmpty : ! selectFolders && ! spec . folderType }
499498 ) ,
500499 } ) ) . filter ( ( section ) => section . nodes . length > 0 )
501- } , [ groups , structureFolders ] )
500+ } , [ groups , structureFolders , selectFolders ] )
502501}
503502
504503interface ResourceMenuSectionsProps {
0 commit comments