import { WorkspaceFileReference, WorkspaceFileReferencePrefetchReason, WorkspaceFileReferencePrefetchState, WorkspaceFileReferenceTreeSnapshot, WorkspaceFileReferenceAdapter, ReferenceNode, ReferenceScope, ReferenceSearchPagination, ReferenceLocateTarget, ReferenceProvenanceFilter, SelectedReference, ReferenceHandle, ReferenceProvenanceCatalog, ReferenceProvenanceDimension } from '../contracts/index.js'; import * as react from 'react'; import { WorkspaceFilePreviewKind, WorkspaceFilePreviewReadonlyReason } from '@tutti-os/workspace-file-preview'; import { a as ReferenceSourceAggregator, b as ReferenceSourceTab } from '../referenceSourceAggregator-CC-K1EfG.js'; import '@tutti-os/workspace-file-manager/services'; declare const workspaceFileReferenceDefaultExpandedDepth = 4; interface WorkspaceFileReferenceDirectoryState { displayPath: string; entries: WorkspaceFileReference[]; loaded: boolean; loading: boolean; prefetchReason?: WorkspaceFileReferencePrefetchReason | null; prefetchState?: WorkspaceFileReferencePrefetchState | null; } declare function normalizeDirectoryPath(path: string): string; declare function collectVisibleTreeEntries(entries: readonly WorkspaceFileReference[], directoryStateByPath: Record, expandedFolderPaths: Record): WorkspaceFileReference[]; declare function mergeExpandedFolderPaths(current: Record, prefetched: Record): Record; declare function mergePrefetchedDirectoryState(current: Record, prefetched: Record): Record; declare function createWorkspaceFileReferenceDirectoryStateFromSnapshot(snapshot: WorkspaceFileReferenceTreeSnapshot): Record; declare function prefetchReferenceTree(input: { listDirectory: (path: string) => Promise<{ displayPath: string; entries: WorkspaceFileReference[]; normalizedPath: string; } | null>; maxDepth: number; path: string; depth?: number; }): Promise<{ directoryStateByPath: Record; expandedFolderPaths: Record; }>; type WorkspaceFileReferencePickerMode = "browse" | "search"; type WorkspaceFileReferencePreviewState = { status: "directory"; reference: WorkspaceFileReference; } | { status: "empty"; } | { status: "error"; reference: WorkspaceFileReference; } | { status: "image"; objectUrl: string; previewKind: "image"; reference: WorkspaceFileReference; } | { previewKind?: WorkspaceFilePreviewKind; reference: WorkspaceFileReference; status: "loading"; } | { status: "video"; objectUrl: string; previewKind: "video"; reference: WorkspaceFileReference; } | { maxSizeBytes?: number; reason: WorkspaceFilePreviewReadonlyReason; reference: WorkspaceFileReference; status: "readonly"; } | { status: "text"; content: string; previewKind: WorkspaceFilePreviewKind; reference: WorkspaceFileReference; } | { status: "unsupported"; reference: WorkspaceFileReference; } | { status: "unavailable"; reference: WorkspaceFileReference; }; interface UseWorkspaceFileReferencePickerViewInput { fileAdapter?: WorkspaceFileReferenceAdapter; initialPath?: string | null; onClose: () => void; onConfirm: (refs: WorkspaceFileReference[]) => void; open: boolean; workspaceId: string; } declare function useWorkspaceFileReferencePickerView({ fileAdapter, initialPath, onClose, onConfirm, open, workspaceId }: UseWorkspaceFileReferencePickerViewInput): { browseRootEntries: WorkspaceFileReference[]; directoryStateByPath: Record; expandedFolderPaths: Record; focusedEntry: WorkspaceFileReference | null; focusedPath: string | null; isLoading: boolean; mode: WorkspaceFileReferencePickerMode; previewState: WorkspaceFileReferencePreviewState; searchQuery: string; selectedRefs: WorkspaceFileReference[]; visibleEntries: WorkspaceFileReference[]; setFocusedPath: react.Dispatch>; setSearchQuery: (query: string) => void; toggleFolder: (entry: WorkspaceFileReference) => void; toggleRef: (ref: WorkspaceFileReference) => void; }; interface ReferenceSearchResultBlock { readonly entryCount: number; readonly pages: readonly (readonly ReferenceNode[])[]; /** Page starts relative to this block. */ readonly pageStarts: readonly number[]; /** First result index represented by this block. */ readonly startIndex: number; } interface ReferenceSearchResultIndex { readonly entryCount: number; readonly pageCount: number; readonly sealedBlocks: readonly ReferenceSearchResultBlock[]; readonly tailBlock: ReferenceSearchResultBlock | null; } /** * node-keyed 多源 picker 的逻辑层 controller(顶部分源 tab)。 * 独立于现有 WorkspaceFileReferencePickerController —— issue-manager 不受影响。 * 设计见 docs/architecture/agent-reference-source-services.md §2 / §3。 * * 本层只管:tabs、per-source inline 展开树(node-keyed)、cursor 加载更多、 * per-tab 搜索、跨 tab 选中集、confirm。预览/打开留待 UI 接入步骤。 */ type ReferenceSourcePickerMode = "browse" | "search"; type ReferencePickerSelectionMode = "multiple" | "single"; interface ReferenceSourceNodeChildrenState { /** 已累积的子节点(含多页 append)。 */ entries: ReferenceNode[]; nextCursor: string | null; loaded: boolean; loading: boolean; error: Error | null; } interface ReferenceSourceTabState { sourceId: string; expandedKeys: Record; /** key = nodeRefKey;源根用 ROOT_CHILDREN_KEY。 */ childrenByKey: Record; mode: ReferenceSourcePickerMode; searchQuery: string; /** 已选文件类型筛选分类 id(全局统一口径);与 searchQuery 一起构成「查询」。 */ searchFilters: string[]; /** 当前搜索限定的二级分组节点 nodeId(左栏选中分组);null = 跨整源搜索。 */ searchScopeNodeId: string | null; /** Immutable bounded-block index for random access by the virtualized view. */ searchResultIndex: ReferenceSearchResultIndex; /** Changes only when a first page replaces the current result identity. */ searchResultIdentity: number; /** 去重后实际展示的搜索结果数量。 */ searchResultCount: number; searchNextCursor: string | null; /** 当前查询实际采用的分页协议;结果可覆盖 source 的默认 capability。 */ searchPagination: ReferenceSearchPagination; /** 当前搜索请求的 limit;legacy 分页据此按 SEARCH_PAGE_SIZE 递增。 */ searchLimit: number; /** cursor 分页以 nextCursor 为准;兼容模式以请求上限和全局上限推断。 */ searchHasMore: boolean; /** 正在加载下一页;用于底部 spinner,不清空已有结果。 */ isSearchLoadingMore: boolean; isSearchLoading: boolean; searchError: Error | null; } interface ReferenceSourcePickerSnapshot { isLoadingTabs: boolean; /** 本次打开是否已成功刷新 Source Catalog;缓存 Tab 不代表路由已就绪。 */ tabsValidated: boolean; tabsError: Error | null; tabs: ReferenceSourceTab[]; activeSourceId: string | null; bySource: Record; /** 跨 tab 累积的选中文件节点,按选中顺序。 */ selection: ReferenceNode[]; } /** confirmGrouped 的产物:一个 navigable 源文件夹 = 一个 bundle(保留分组)。 */ interface ReferenceConfirmBundle { /** 被选中的文件夹节点(提供 displayName / iconUrl / ref 作为 bundle 身份)。 */ root: ReferenceNode; /** * 该 bundle 归一成的可被 agent 解析的领域句柄(见 ReferenceHandle)。 * 由所属源 describeReferenceHandle 解码;发给 agent 的 `mention://workspace-reference/...` * 由它构造,替代把文件路径全部展开。源不支持解码时为 null。 */ handle: ReferenceHandle | null; } interface ReferenceConfirmGroupedResult { /** 单独选中的文件 + 非 navigable 源的文件夹(保持单条引用)。 */ files: SelectedReference[]; /** 每个 navigable 源文件夹一项,文件已折叠在内。 */ bundles: ReferenceConfirmBundle[]; } interface ReferenceSourcePickerController { readonly store: ReferenceSourcePickerSnapshot; getSnapshot(): ReferenceSourcePickerSnapshot; open(): void; close(): void; reset(cachedTabs?: readonly ReferenceSourceTab[]): void; setActiveSource(sourceId: string, scopeNodeId?: string | null): void; /** * 把「定位目标」解析为从源根到目标的真实 ReferenceNode 路径(root → leaf)。 * 纯数据解析:逐层 listChildren 找到真实节点(带 displayName 等),不改动任何 UI/导航态。 * 源不支持定位 / 未找到时返回部分路径(可能为空)。供「打开即定位」一次性应用。 */ locatePath(target: ReferenceLocateTarget): Promise; /** 确保某节点(null=当前源根)的子节点已加载(抽屉式导航进入用,不切换展开态)。 */ ensureChildren(node: ReferenceNode | null): void; /** 重新拉取某节点(null=当前源根)的子节点第一页,用于应用/议题等动态源刷新已加载分组。 */ refreshChildren(node: ReferenceNode | null): void; /** 确保指定源的根层级已加载(左栏可同时展开多源时,为非 active 源预载分组)。 */ ensureSourceRoot(sourceId: string): void; /** 幂等展开某 folder 并确保其子节点已加载(定位目标默认展开用)。 */ expandNode(node: ReferenceNode): void; toggleNode(node: ReferenceNode): void; loadMore(node: ReferenceNode | null): void; /** * 拉取指定源根层级的下一页(左栏二级分组分页用)。 * 与 loadMore(null) 的区别:后者只作用于 active 源;本方法显式指定源, * 使左栏任一源(无论是否 active)都能继续拉取其分组。 */ loadMoreSourceRoot(sourceId: string): void; /** * 设置搜索关键词。scopeNodeId 指定把搜索限定在 active 源内某个二级分组(左栏选中分组) * 的节点 nodeId;缺省/null = 跨整源搜索。关键词、provenance 约束,以及声明 * filtersUseSearch 的源上的类型筛选会进入扁平查询态。 */ setSearchQuery(query: string, scopeNodeId?: string | null): void; /** * 设置已选文件类型筛选分类(全局统一口径)。默认无关键词时保持可导航的浏览树; * 有关键词或源声明 filtersUseSearch 时作为搜索参数下钻到 source。 */ setSearchFilters(filters: string[], scopeNodeId?: string | null): void; setProvenanceFilter(filter: ReferenceProvenanceFilter | null, scopeNodeId?: string | null): void; /** 搜索进行中切换左栏分组时更新限定范围并以现有关键词/筛选重搜。 */ setSearchScope(scopeNodeId: string | null): void; /** Retry the current query from page one without changing its identity inputs. */ retrySearch(): void; /** * 加载更多查询结果:cursor source 拉取固定大小的下一页并增量 append;legacy source * 以同一关键词/筛选、更大的 limit 重查并整体替换。无更多 / 在途 / 非查询态时 no-op。 */ loadMoreSearch(): void; createDirectory(parent: ReferenceNode | null, name: string): Promise; toggleSelection(node: ReferenceNode): void; toggleSingleSelectionAndExpand(node: ReferenceNode): void; clearSelection(): void; /** * 选中归一。文件 → 单条;文件夹按所属源区分: * - 本地(非 navigable)源:保持单条 folder 引用(filesystem 路径与目录一一对应); * - app/issue(navigable)源:其文件夹下文件在 filesystem 里不一定落在该目录路径下, * 故递归 listChildren 枚举,展开成多条文件引用。 * 含异步枚举,故返回 Promise;结果按 path 去重、保序。 */ confirm(selection?: readonly ReferenceNode[]): Promise; /** * 与 confirm 同源,但保留分组:navigable 源的每个选中文件夹折叠成一个 bundle * (文件已递归展开在内),其余作为单条文件。供「文件夹 = 一个节点」的插入形态用。 */ confirmGrouped(selection?: readonly ReferenceNode[]): Promise; } interface CreateReferenceSourcePickerControllerInput { aggregator: ReferenceSourceAggregator; scope: ReferenceScope; selectionMode?: ReferencePickerSelectionMode; /** 关键词搜索允许返回的节点类型。 */ searchResultKind?: ReferenceNode["kind"]; searchDebounceMs?: number; onTabsLoaded?: (tabs: readonly ReferenceSourceTab[]) => void; } /** 源根 children 的 key(node===null 时)。 */ declare const ROOT_CHILDREN_KEY: string; declare function createReferenceSourcePickerController(input: CreateReferenceSourcePickerControllerInput): ReferenceSourcePickerController; declare function invalidateReferenceSourceTabRuntimeCache(aggregator: ReferenceSourceAggregator, workspaceId?: string): void; /** * 权限/Host 能力变化时统一清理可见 Tab 快照并取消关联的在途读取。 * 二级分组和目录内容属于单次打开状态,不进入这里的跨打开缓存。 */ declare function invalidateReferenceSourcePickerRuntimeCache(aggregator: ReferenceSourceAggregator, workspaceId?: string): void; interface ReferenceProvenanceFilterSnapshot { catalog: ReferenceProvenanceCatalog; value: ReferenceProvenanceFilter; } interface ReferenceProvenanceFilterController { getSnapshot(): ReferenceProvenanceFilterSnapshot; subscribe(listener: () => void): () => void; setCatalog(catalog: ReferenceProvenanceCatalog): void; setValue(value: ReferenceProvenanceFilter): void; toggle(dimension: ReferenceProvenanceDimension, id: string): void; toggleAll(dimension: ReferenceProvenanceDimension): void; reset(): void; } declare function createReferenceProvenanceFilterController(initialCatalog?: ReferenceProvenanceCatalog): ReferenceProvenanceFilterController; declare function useReferenceProvenanceFilter(controller: ReferenceProvenanceFilterController): ReferenceProvenanceFilterSnapshot; declare function useReferenceProvenanceFilterCatalog(injectedCatalog: ReferenceProvenanceCatalog): { snapshot: { catalog: ReferenceProvenanceCatalog; value: ReferenceProvenanceFilter; }; controller: { reset: () => void; toggle: (dimension: ReferenceProvenanceDimension, id: string) => void; toggleAll: (dimension: ReferenceProvenanceDimension) => void; }; }; export { type CreateReferenceSourcePickerControllerInput, ROOT_CHILDREN_KEY, type ReferenceProvenanceFilterController, type ReferenceProvenanceFilterSnapshot, type ReferenceSearchResultBlock, type ReferenceSearchResultIndex, type ReferenceSourceNodeChildrenState, type ReferenceSourcePickerController, type ReferenceSourcePickerMode, type ReferenceSourcePickerSnapshot, type ReferenceSourceTabState, type UseWorkspaceFileReferencePickerViewInput, type WorkspaceFileReferenceDirectoryState, type WorkspaceFileReferencePreviewState, collectVisibleTreeEntries, createReferenceProvenanceFilterController, createReferenceSourcePickerController, createWorkspaceFileReferenceDirectoryStateFromSnapshot, invalidateReferenceSourcePickerRuntimeCache, invalidateReferenceSourceTabRuntimeCache, mergeExpandedFolderPaths, mergePrefetchedDirectoryState, normalizeDirectoryPath, prefetchReferenceTree, useReferenceProvenanceFilter, useReferenceProvenanceFilterCatalog, useWorkspaceFileReferencePickerView, workspaceFileReferenceDefaultExpandedDepth };