Skip to content
Source
Sign inSign up

projectRemoval.ts

57 lines2.5 KB

1import { isListedThreadLineage } from "@t3tools/contracts";
2​
3import type { EnvironmentProject, EnvironmentThreadShell } from "./models.ts";
4​
5export function planProjectRemoval<
6 Thread extends Pick<EnvironmentThreadShell, "environmentId" | "projectId" | "lineage">,
7>(options: {
8 readonly members: ReadonlyArray<
9 Pick<EnvironmentProject, "id" | "environmentId" | "title" | "workspaceRoot"> & {
10 readonly environmentLabel?: string | null;
11 }
12 >;
13 readonly groupMemberCount: number;
14 readonly hasOtherMembers: boolean;
15 readonly displayName: string;
16 readonly threads: ReadonlyArray<Thread>;
17 /** The members' threads this client does not hold: older settled threads its shell left out. */
18 readonly unloadedThreadCount?: number;
19}) {
20 const { members, groupMemberCount, hasOtherMembers, displayName, threads } = options;
21 const memberKeys = new Set(members.map((member) => `${member.environmentId}:${member.id}`));
22 const projectThreads = threads.filter((thread) =>
23 memberKeys.has(`${thread.environmentId}:${thread.projectId}`),
24 );
25 // Side chats and subagents go with their parent but never show in thread lists.
26 const threadCount =
27 projectThreads.filter((thread) => isListedThreadLineage(thread.lineage)).length +
28 (options.unloadedThreadCount ?? 0);
29 const isWholeGroup = members.length === groupMemberCount;
30 const targetKind = hasOtherMembers || !isWholeGroup ? "checkout" : "project";
31 const singleMember = members.length === 1 ? members[0]! : null;
32 const targetLabel = singleMember?.title ?? displayName;
33 const confirmationMessage = [
34 threadCount > 0
35 ? `Remove ${targetKind} "${targetLabel}" and delete its ${threadCount} thread${threadCount === 1 ? "" : "s"}?`
36 : `Remove ${targetKind} "${targetLabel}"?`,
37 ...(singleMember
38 ? [
39 `Path: ${singleMember.workspaceRoot}`,
40 ...(singleMember.environmentLabel
41 ? [`Environment: ${singleMember.environmentLabel}`]
42 : []),
43 ]
44 : [`This removes ${members.length} grouped project entries.`]),
45 ...(threadCount > 0
46 ? [
47 "Those threads and any archived threads are deleted from T3 Code. Provider sessions are kept.",
48 ]
49 : ["Any archived threads are deleted from T3 Code. Provider sessions are kept."]),
50 isWholeGroup && !hasOtherMembers
51 ? "This removes only the project entries, not the files on disk."
52 : "Other entries in this grouped project are unaffected.",
53 "This action cannot be undone.",
54 ].join("\n");
55​
56 return { projectThreads, isWholeGroup, targetKind, confirmationMessage };