返回 DeepSeek-Reasonix
sessionCatalogBridge.ts
根目录 / desktop / frontend / src / lib / sessionCatalogBridge.ts
1 import { asArray } from "./array";
2 import { desktopHost } from "./desktopHost";
3 import { mockProjectGroups } from "./mockProjectTreeOrganization";
4 import { mockReadSnapshotPage, releaseMockReadSnapshot } from "./mockReadSnapshot";
5 import type {
6 ProjectNode,
7 ProjectTopicKey,
8 ProjectTopicPage,
9 ProjectTopicPageRequest,
10 ProjectTreeChangedV2,
11 SessionCatalogBindings,
12 } from "./types";
13
14 export function onProjectTreeChangedV2(cb: (event: ProjectTreeChangedV2) => void): () => void {
15 const host = desktopHost();
16 if (host.kind !== "none") {
17 return host.events.on("project-tree:changed-v2", (payload?: unknown) => {
18 if (!payload || typeof payload !== "object") return;
19 const event = payload as Partial<ProjectTreeChangedV2>;
20 cb({
21 revision: typeof event.revision === "number" ? event.revision : 0,
22 roots: asArray(event.roots).filter((root): root is string => typeof root === "string"),
23 reason: typeof event.reason === "string" ? event.reason : "changed",
24 });
25 });
26 }
27 return () => {};
28 }
29
30 export function makeMockSessionCatalogBindings(cloneProjectTree: () => ProjectNode[]): SessionCatalogBindings {
31 const listProjectTopics = async (req: ProjectTopicPageRequest): Promise<ProjectTopicPage> => {
32 const folder = req.scope === "global"
33 ? cloneProjectTree().find((item) => item.kind === "global_folder")
34 : cloneProjectTree().find((item) => item.kind === "project" && item.root === req.workspaceRoot);
35 const query = (req.query ?? "").trim().toLocaleLowerCase();
36 const created = req.sortMode === "created";
37 const groups = mockProjectGroups(req.scope, req.workspaceRoot ?? "");
38 const grouped = new Set(groups.flatMap((group) => group.topicIds ?? []));
39 const selectedGroup = groups.find((group) => group.id === req.groupId);
40 const all = asArray(folder?.children)
41 .filter((item) => !query || item.label.toLocaleLowerCase().includes(query))
42 .filter((item) => !req.excludePinned || !item.pinned)
43 .filter((item) => req.groupFilter !== "ungrouped" || !grouped.has(item.topicId ?? ""))
44 .filter((item) => req.groupFilter !== "group" || Boolean(selectedGroup?.topicIds?.includes(item.topicId ?? "")))
45 .sort((left, right) => Number(Boolean(right.pinned)) - Number(Boolean(left.pinned))
46 || (created ? right.createdAt || right.lastActivityAt || 0 : right.lastActivityAt || right.createdAt || 0)
47 - (created ? left.createdAt || left.lastActivityAt || 0 : left.lastActivityAt || left.createdAt || 0)
48 || (left.topicId ?? "").localeCompare(right.topicId ?? ""));
49 return {
50 ...mockReadSnapshotPage("project-topics", [req.scope, req.workspaceRoot, query, req.sortMode, req.groupFilter, req.groupId, req.excludePinned], req.cursor, req.limit, all),
51 revision: 1,
52 complete: true,
53 readyDirectories: 1,
54 pendingDirectories: 0,
55 failedDirectories: 0,
56 };
57 };
58 return {
59 async ReleaseReadSnapshot(id: string) { releaseMockReadSnapshot(id); },
60 async GetProjectTreeSnapshot() {
61 return {
62 revision: 1,
63 projects: cloneProjectTree().map((project) => ({
64 ...project,
65 children: asArray(project.children).filter((topic) => Boolean(topic.pinned)),
66 })),
67 catalog: { state: "ready", mode: "memory", revision: 1, indexed: 4, total: 4, repairPending: 0, sourceCount: 4, unindexedTargetCount: 0, canRebuild: false },
68 indexed: 4,
69 total: 4,
70 indexingDone: true,
71 };
72 },
73 ListProjectTopics: listProjectTopics,
74 async GetTopicSummary(key: ProjectTopicKey) {
75 const page = await listProjectTopics({ scope: key.scope, workspaceRoot: key.workspaceRoot, limit: 200 });
76 return page.items.find((item) => item.topicId === key.topicId)
77 ?? { key: "", kind: key.scope === "global" ? "global_topic" : "topic", label: "", children: [] };
78 },
79 async GetSessionCatalogStatus() {
80 return { state: "ready", mode: "memory", revision: 1, indexed: 4, total: 4, repairPending: 0, sourceCount: 4, unindexedTargetCount: 0, canRebuild: false };
81 },
82 async RebuildSessionCatalog() {},
83 };
84 }
85
85 lines TYPESCRIPT