import { WorkspaceFileOpenWithApplication } from '@tutti-os/workspace-file-manager/services'; import { WorkspaceFilePreviewKind } from '@tutti-os/workspace-file-preview'; type ReferenceProvenanceDimension = "agent" | "member"; interface ReferenceProvenanceFilter { /** null means this dimension does not constrain the query. */ agentTargetIds: readonly string[] | null; /** Reserved for collaboration hosts. Personal Tutti does not enable it. */ memberIds: readonly string[] | null; } interface ReferenceProvenanceOption { id: string; label: string; iconUrl?: string | null; disabled?: boolean; /** Lets collaboration hosts describe ownership without changing filter semantics. */ parentMemberId?: string | null; } interface ReferenceProvenanceCatalog { enabledDimensions: readonly ReferenceProvenanceDimension[]; agentOptions: readonly ReferenceProvenanceOption[]; memberOptions: readonly ReferenceProvenanceOption[]; } declare const EMPTY_REFERENCE_PROVENANCE_FILTER: ReferenceProvenanceFilter; /** * Reference Source Services 契约。 * * 当前架构见 docs/architecture/agent-reference-sources.md。 * 把「+」文件引用弹窗从单一数据源升级为可插拔的多源服务层: * 本地文件 / 应用内产物 / 任务中心产物,每个一个 ReferenceSourceService。 */ /** * 不透明、源内作用域的节点句柄。 * picker 永不解析 nodeId —— 只整体持有、原样回传给所属源。 */ interface NodeRef { /** "workspace-file" | "app-artifact" | "task-artifact" ... */ sourceId: string; /** 源内不透明标识。本地源 = path;应用产物源 = 编码后的 app/group/file 句柄。 */ nodeId: string; } /** 统一树节点。identity = NodeRef。folder 可有子节点,file 不可。 */ interface ReferenceNode { ref: NodeRef; kind: "folder" | "file"; displayName: string; /** * 可选的「上下文标签」:搜索结果里展示该项的归属(如应用名 / 议题标题), * 各源需要展示上下文时自行填充。picker 不得把不透明 nodeId 当作展示文案。 */ contextLabel?: string | null; /** folder 是否可下钻(懒加载箭头)。 */ hasChildren?: boolean; /** 可选数量,如 app group 的 referenceCount。 */ childCount?: number | null; /** 可选图标(data URL / 远程 URL),如应用产物源的 app 图标;有则替代默认文件夹图标。 */ iconUrl?: string | null; createdTimeMs?: number | null; sizeBytes?: number | null; mtimeMs?: number | null; mimeType?: string | null; } /** 所有源操作的上下文。 */ type ReferenceScope = WorkspaceFileReferenceScope; interface ListChildrenInput { /** null = 该源根层级。 */ node: NodeRef | null; /** 续页游标;本地源恒不返回。 */ cursor?: string | null; /** 当前层过滤(可选)。协议层只过滤直接子项,非递归。 */ filter?: string | null; signal?: AbortSignal; } interface ListChildrenResult { entries: ReferenceNode[]; /** null/undefined 表示无更多。 */ nextCursor?: string | null; /** * 源已自行排序、picker 不应再重排时置 true(如「最近访问」按访问时间倒序)。 * 缺省/false:picker 首屏按 folder 在前 + 名称排序。 */ ordered?: boolean; } interface LoadSidebarGroupsInput { /** 续页游标;二级分组不与目录 children 共享分页状态。 */ cursor?: string | null; signal?: AbortSignal; } /** * 左栏二级分组的独立读取结果。 * * 二级分组是导航目录,不是目录内容缓存。Picker 每次打开都重新读取, * 并把结果保存在本次打开的临时状态中。 */ interface LoadSidebarGroupsResult { entries: ReferenceNode[]; nextCursor?: string | null; /** 源已自行排序时置 true,Picker 不再按名称重排。 */ ordered?: boolean; /** 非 navigable 源是否应在本次打开时自动进入第一个固定位置。 */ autoSelectFirst?: boolean; } interface SearchInput { query: string; /** * 允许出现在搜索结果里的节点类型。source 必须在分页/limit 前执行该约束。 * 缺省表示调用方不限制结果类型。 */ kinds?: Array; /** Host-controlled provenance constraint. Sources must filter before paging. */ provenanceFilter?: ReferenceProvenanceFilter | null; /** * 已选「文件类型筛选分类」id 数组(全局统一口径,见 core/referenceFilterCategories)。 * 仅在关键字搜索时下钻到 source/daemon,并在分页/limit 前执行。 * 浏览态由 picker 递归加载并投影整棵源树;只有包含匹配文件的文件夹会保留。 * 空数组/缺省 = 不按类型过滤。 */ filters?: string[]; cursor?: string | null; limit?: number; signal?: AbortSignal; /** * 可选:把搜索限定在该源内某个二级分组(左栏选中的「分组节点」nodeId,源内不透明)。 * 缺省/null = 跨整源搜索(历史行为)。例如应用产物源传入选中 app 的分组节点, * 即「只搜该应用」而非所有应用。源自行解释此 nodeId;不支持的源可忽略。 */ withinNodeId?: string | null; } /** * Search continuation semantics are independent from browse pagination. * Legacy sources grow `limit` and return the complete prefix; cursor sources * return only the requested page and a continuation cursor. */ type ReferenceSearchPagination = "cursor" | "legacy"; interface SearchResult { entries: ReferenceNode[]; nextCursor?: string | null; /** Overrides the source capability for this search result/query. */ searchPagination?: ReferenceSearchPagination; } /** 预览内容(复用 workspace 预览结构)。 */ type ReferencePreview = WorkspaceFileReferencePreview; /** * 选中的「分组节点」归一成的可被 agent 解析的引用句柄。 * 与发给 agent 的 `mention://workspace-reference/?source=...` 一一对应: * - app: { source:"app", id: appId, groupId? }(groupId = app 子分组) * - task: { source:"task", id: topicId, groupId? }(groupId = issueId;缺省 = 整个 topic) * 各源把自家不透明 nodeId 解码成此领域句柄;picker 自身不解析。 */ interface ReferenceHandle { source: "app" | "task"; /** 顶层容器 id:appId / topicId。 */ id: string; /** 子级 id:app 子分组 / issueId。缺省表示整个容器。 */ groupId?: string; } /** * 「定位到某分组」目标:打开 picker 时直达某事项/应用分组用。 * params 为源内不透明语义参数,由各源 backend 自行解释: * - 应用产物源:{ appId } * - 议题产出源:{ issueId, topicId? } */ interface ReferenceLocateTarget { /** 目标所属源(= picker tab / ReferenceSourceService.metadata.id)。 */ sourceId: string; params: Record; } /** * 选中 → 插入 composer 的产物。 * 统一形态:所有源最终都归一为一个文件路径,与现有 picker 逐字段一致, * composer / 序列化 / agent 侧零改动。 */ interface SelectedReference { /** 应用产物 = daemon 解析的绝对路径;本地 = /workspace 逻辑路径。 */ path: string; kind: "file" | "folder"; displayName?: string; sizeBytes?: number | null; /** Host-local original path, when path is an opaque transfer handle. */ hostPath?: string; /** 保留引用来源,供上层区分 workspace 文件与 host 本地文件等同形 path。 */ sourceId?: string; } interface ReferenceSourceMetadata { id: string; label: string; icon?: string; /** 根层级排序,小者在前。 */ order: number; } interface ReferenceSourceCapabilities { searchable: boolean; previewable: boolean; /** Whether listChildren() supports browse cursors. */ paginated: boolean; /** * Search pagination semantics. Omitted sources use the legacy growing-limit * protocol even when browse pagination (`paginated`) is enabled. */ searchPagination?: "cursor"; /** 是否展示左侧分组导航(master-detail)。本地源 false;应用/任务源 true。 */ navigable?: boolean; /** * 是否支持「全局文件类型筛选」(图片/文档/表格…)。为 true 时 picker 展示筛选下拉, * 搜索态下已选分类作为 search() 的 filters 下钻到 source;无关键词时默认由 picker * 递归投影浏览树。三源(本地/应用/任务)均为 true。 */ filterable?: boolean; /** * 无关键词、只有文件类型筛选时是否走 search(),而非由 picker 递归 listChildren() * 投影浏览树。仅对同时支持 filterable/searchable/search() 的源有效。Host-local 等 * 权限敏感源可开启,避免筛选时递归触碰未授权目录。 */ filtersUseSearch?: boolean; /** 是否允许 picker 在该源的目录下创建子目录。 */ directoryCreatable?: boolean; /** Provenance dimensions this source can enforce before pagination. */ provenanceDimensions?: readonly ReferenceProvenanceDimension[]; } /** * 单源契约。各源自治:取数 / open / preview 各自负责。 * 形状处理(kind 映射、排序去重、预览类型、cursor 累积、nodeKey 归一)走共享 base 工具。 */ interface ReferenceSourceService { readonly metadata: ReferenceSourceMetadata; readonly capabilities: ReferenceSourceCapabilities; /** 动态可用性。如:无支持 references 的 app 时应用产物源返回 false。 */ isAvailable(scope: ReferenceScope, signal?: AbortSignal): boolean | Promise; /** * 独立读取左栏二级分组。Picker 不再从 listChildren(source-root) 推导左栏, * 避免把导航数据写入目录缓存。结果只在本次 Picker 打开期间保留。 */ loadSidebarGroups(scope: ReferenceScope, input: LoadSidebarGroupsInput): Promise; listChildren(scope: ReferenceScope, input: ListChildrenInput): Promise; /** * 可选:把语义定位参数解析为从源根到目标分组的 NodeRef 路径(root → leaf), * 供 picker 打开时逐层展开/聚焦。返回 null 表示不支持或未找到。 */ locateTarget?(scope: ReferenceScope, params: Record): Promise; /** * 可选:把一个「分组节点」解码成可被 agent 解析的领域句柄(见 ReferenceHandle)。 * navigable 源(app/task)实现;返回 null 表示该节点不是可引用的分组。 * 用于把选中的文件夹折叠成一条 `mention://workspace-reference/...`,而非展开成文件路径。 */ describeReferenceHandle?(node: ReferenceNode): ReferenceHandle | null; search?(scope: ReferenceScope, input: SearchInput): Promise; /** * 可选:在 parent(null = 源根)下创建一个直接子目录并返回其 canonical picker 节点。 * 路径拼接、名称校验和越界防护由源负责,picker 不解释不透明 nodeId。 */ createDirectory?(scope: ReferenceScope, input: { parent: ReferenceNode | null; name: string; }): Promise; open?(scope: ReferenceScope, node: ReferenceNode): Promise; listOpenWithApplications?(scope: ReferenceScope, node: ReferenceNode): Promise; openWithApplication?(scope: ReferenceScope, node: ReferenceNode, applicationPath: string): Promise; openWithOtherApplication?(scope: ReferenceScope, node: ReferenceNode, applicationPickerPrompt?: string): Promise; reveal?(scope: ReferenceScope, node: ReferenceNode): Promise; readPreview?(scope: ReferenceScope, node: ReferenceNode): Promise; /** 选中产物归一,见 SelectedReference。 */ resolveSelection(node: ReferenceNode): SelectedReference; /** * 可选的确认阶段 preparation。仅当 source 返回的 selection 尚不是 consumer 可直接读取的 * locator 时实现,例如 host 需要先把 capability handle 物化到 provider runtime。 * picker 会等待 preparation 完成;失败时不得提交部分结果或关闭弹窗。 */ prepareSelection?(scope: ReferenceScope, node: ReferenceNode, selection: SelectedReference): Promise; } interface ReferenceSourceRegistry { /** 已按 isAvailable 过滤、按 metadata.order 排序。 */ getSources(scope: ReferenceScope, input?: { signal?: AbortSignal; }): Promise; } interface WorkspaceFileReference { createdTimeMs?: number | null; displayName?: string; hostPath?: string; kind: "file" | "folder" | (string & {}); mtimeMs?: number | null; path: string; sizeBytes?: number | null; sourceId?: string; } interface WorkspaceFileReferenceDirectoryListing { directoryPath: string; entries: WorkspaceFileReference[]; rootPath?: string | null; } type WorkspaceFileReferencePrefetchState = "loaded" | "partial" | "not_loaded" | "unavailable" | (string & {}); type WorkspaceFileReferencePrefetchReason = "budget_exhausted" | "depth_limit_reached" | "unreadable" | (string & {}); interface WorkspaceFileReferenceTreeDirectory { directoryPath: string; entries: WorkspaceFileReferenceTreeEntry[]; prefetchReason?: WorkspaceFileReferencePrefetchReason | null; prefetchState: WorkspaceFileReferencePrefetchState; } interface WorkspaceFileReferenceTreeEntry extends WorkspaceFileReference { hasChildren?: boolean; prefetchReason?: WorkspaceFileReferencePrefetchReason | null; prefetchState?: WorkspaceFileReferencePrefetchState | null; prefetchedDirectory?: WorkspaceFileReferenceTreeDirectory | null; } interface WorkspaceFileReferenceTreeSnapshot { budgetExceeded: boolean; directory: WorkspaceFileReferenceTreeDirectory; prefetchBudgetMs: number; prefetchDepth: number; rootPath: string; } /** Optional host override of classified preview kind for a preview read. */ type WorkspaceFileReferencePreviewKind = WorkspaceFilePreviewKind; interface WorkspaceFileReferencePreview { bytes: Uint8Array | ArrayBuffer; contentType?: string | null; kind?: WorkspaceFileReferencePreviewKind; } interface WorkspaceFileReferenceScope { workspaceId: string; } interface WorkspaceFileReferenceAdapter { loadReferenceTree?(input: WorkspaceFileReferenceScope & { path?: string | null; prefetchBudgetMs?: number; prefetchDepth?: number; }): Promise; listDirectory?(input: WorkspaceFileReferenceScope & { path?: string | null; }): Promise; listRecentReferences?(input: WorkspaceFileReferenceScope & { limit?: number; signal?: AbortSignal; }): Promise; openReference?(reference: WorkspaceFileReference): Promise | void; listOpenWithApplications?(reference: WorkspaceFileReference): Promise; openReferenceWithApplication?(reference: WorkspaceFileReference, applicationPath: string): Promise | void; openReferenceWithOtherApplication?(reference: WorkspaceFileReference, applicationPickerPrompt?: string): Promise | void; revealReference?(reference: WorkspaceFileReference): Promise | void; readReferencePreview?(input: WorkspaceFileReferenceScope & { reference: WorkspaceFileReference; }): Promise; refreshTree?(input: WorkspaceFileReferenceScope & { depth?: number; paths?: readonly string[]; }): Promise; requestReferences?(input: WorkspaceFileReferenceScope): Promise; searchReferences?(input: WorkspaceFileReferenceScope & { limit?: number; query: string; /** 搜索结果类型约束,必须在 limit 前执行。 */ kinds?: Array<"file" | "folder">; /** 已选文件类型筛选分类 id;仅在有关键词的搜索中下钻。 */ filters?: string[]; /** * 可选:把搜索限定在工作区根下的某子路径(左栏选中的「位置」,如 文稿/下载/桌面)。 * 相对工作区根的逻辑路径;缺省/空 = 跨整根搜索。 */ within?: string; signal?: AbortSignal; }): Promise; } interface WorkspaceFileReferenceCopy { t(key: string, values?: Record): string; } export { EMPTY_REFERENCE_PROVENANCE_FILTER, type ListChildrenInput, type ListChildrenResult, type LoadSidebarGroupsInput, type LoadSidebarGroupsResult, type NodeRef, type ReferenceHandle, type ReferenceLocateTarget, type ReferenceNode, type ReferencePreview, type ReferenceProvenanceCatalog, type ReferenceProvenanceDimension, type ReferenceProvenanceFilter, type ReferenceProvenanceOption, type ReferenceScope, type ReferenceSearchPagination, type ReferenceSourceCapabilities, type ReferenceSourceMetadata, type ReferenceSourceRegistry, type ReferenceSourceService, type SearchInput, type SearchResult, type SelectedReference, type WorkspaceFileReference, type WorkspaceFileReferenceAdapter, type WorkspaceFileReferenceCopy, type WorkspaceFileReferenceDirectoryListing, type WorkspaceFileReferencePrefetchReason, type WorkspaceFileReferencePrefetchState, type WorkspaceFileReferencePreview, type WorkspaceFileReferencePreviewKind, type WorkspaceFileReferenceScope, type WorkspaceFileReferenceTreeDirectory, type WorkspaceFileReferenceTreeEntry, type WorkspaceFileReferenceTreeSnapshot };