@xrn1997/dsh-session-delete 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -25
- package/lib/client.js +972 -588
- package/lib/index.js +553 -286
- package/lib/types/api/dispatch.d.ts +2 -2
- package/lib/types/api/route-table.d.ts +1 -1
- package/lib/types/api/trash-rows.d.ts +13 -6
- package/lib/types/client/batch-bar.d.ts +6 -6
- package/lib/types/client/batch-confirm.d.ts +5 -3
- package/lib/types/client/batch-menu-item.d.ts +2 -2
- package/lib/types/client/batch-select.d.ts +7 -50
- package/lib/types/client/batch-selection-store.d.ts +30 -0
- package/lib/types/client/copy.d.ts +4 -1
- package/lib/types/client/delete-confirm.d.ts +2 -0
- package/lib/types/client/host-rows.d.ts +35 -0
- package/lib/types/client/main-view.d.ts +37 -0
- package/lib/types/client/receipt.d.ts +43 -0
- package/lib/types/client/remote.d.ts +16 -6
- package/lib/types/client/store.d.ts +17 -0
- package/lib/types/client/trash-panel.d.ts +1 -1
- package/lib/types/client/trash-store.d.ts +2 -0
- package/lib/types/client/ui/icons.d.ts +3 -3
- package/lib/types/client/undo-toast.d.ts +19 -3
- package/lib/types/client/use-column-resize.d.ts +2 -2
- package/lib/types/client/use-panel-width.d.ts +1 -1
- package/lib/types/client/use-trash-panel-controller.d.ts +55 -0
- package/lib/types/client/write-commit.d.ts +10 -0
- package/lib/types/deps.d.ts +14 -0
- package/lib/types/index.d.ts +6 -13
- package/lib/types/log/zstd-frames.d.ts +1 -1
- package/lib/types/ports/agent-handles.d.ts +25 -0
- package/lib/types/ports/home.d.ts +19 -0
- package/lib/types/ports/host-port.d.ts +58 -28
- package/lib/types/remote/map-error.d.ts +2 -2
- package/lib/types/shared/wire.d.ts +11 -9
- package/lib/types/trash/detail.d.ts +1 -1
- package/lib/types/trash/entry.d.ts +4 -4
- package/lib/types/trash/manifest.d.ts +2 -1
- package/lib/types/trash/reconcile.d.ts +2 -2
- package/lib/types/trash/storage-manifest.d.ts +12 -0
- package/lib/types/verbs/batch.d.ts +1 -1
- package/lib/types/verbs/delete-session.d.ts +8 -11
- package/lib/types/verbs/errors.d.ts +4 -0
- package/lib/types/verbs/member-journal.d.ts +4 -3
- package/lib/types/verbs/member-presence.d.ts +35 -0
- package/lib/types/verbs/orphan-subagents.d.ts +14 -38
- package/lib/types/verbs/permanent-removal.d.ts +113 -0
- package/lib/types/verbs/purge-trash.d.ts +9 -5
- package/lib/types/verbs/restore-session.d.ts +6 -6
- package/package.json +1 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 永久删除的**测量、计划与执行**:一次永久删除(`/list` 的只读读数或 purge / orphan-clean 的删除计划)
|
|
3
|
+
* 之前要记下的事实(目录、字节、账本归属),以及拿到计划之后按它动盘的那一步。计划函数**只读**——
|
|
4
|
+
* 写不写由执行器决定,但活体准入在这里就做掉,调用方拿到计划才允许动盘。
|
|
5
|
+
*/
|
|
6
|
+
import { type TrashEntry } from '../trash/entry.js';
|
|
7
|
+
import type { TrashGroupView } from '../trash/groups.js';
|
|
8
|
+
import type { CoreDeps } from '../deps.js';
|
|
9
|
+
export interface MeasuredMemberDir {
|
|
10
|
+
readonly dir: string;
|
|
11
|
+
readonly bytes: number;
|
|
12
|
+
}
|
|
13
|
+
/** 一条成员被删之前要记下的三件:目录、字节、账本归属(缺席 = 未分组)。`/list` 的只读计划与
|
|
14
|
+
* purge / orphan-clean 的删除计划共用这一份形状。 */
|
|
15
|
+
export interface PlannedMemberRemoval {
|
|
16
|
+
readonly sessionId: string;
|
|
17
|
+
readonly dir: string;
|
|
18
|
+
readonly bytes: number;
|
|
19
|
+
readonly workspaceId?: string;
|
|
20
|
+
}
|
|
21
|
+
/** 成员的盘上目录与字节(扫描、清单装配与 purge 共用这一条路径/存在性/度量口径;
|
|
22
|
+
* 目录缺席回 `undefined`,不拿一份"记录还在、盘上已经没了"的旧读数冒充盘上残留)。 */
|
|
23
|
+
export declare function measureMemberDir(deps: CoreDeps, member: {
|
|
24
|
+
readonly sessionId: string;
|
|
25
|
+
readonly projectDir: string;
|
|
26
|
+
}): Promise<MeasuredMemberDir | undefined>;
|
|
27
|
+
/** 把一组成员折成"删之前要记下的计划";目录不在的成员跳过(记录与盘不一致是那条成员自己的事)。
|
|
28
|
+
* `purge` 的盘上后代、`orphan-clean` 的整组与 `/list` 的盘上残留都走这一处,别再各写一遍
|
|
29
|
+
* measure + workspaceOf。 */
|
|
30
|
+
export declare function planMemberRemovals(deps: CoreDeps, members: readonly {
|
|
31
|
+
readonly sessionId: string;
|
|
32
|
+
readonly projectDir: string;
|
|
33
|
+
}[]): Promise<PlannedMemberRemoval[]>;
|
|
34
|
+
/** 回收站里的一条要删的行:目录、在不在、实测字节(缺席 = 0)。purge 与 `/list` 都由它量。 */
|
|
35
|
+
export interface PlannedTrashRow {
|
|
36
|
+
readonly entry: TrashEntry;
|
|
37
|
+
readonly dir: string;
|
|
38
|
+
readonly present: boolean;
|
|
39
|
+
readonly bytes: number;
|
|
40
|
+
}
|
|
41
|
+
/** `/list` 的一行(一组)所需的只读数:`releaseBytes` 是这一组**实测**会释放的字节。 */
|
|
42
|
+
export interface VisibleTrashGroup extends TrashGroupView {
|
|
43
|
+
readonly trash: readonly PlannedTrashRow[];
|
|
44
|
+
readonly members: readonly PlannedMemberRemoval[];
|
|
45
|
+
readonly releaseBytes: number;
|
|
46
|
+
readonly subagentBytes: number;
|
|
47
|
+
readonly strandedBytes: number;
|
|
48
|
+
readonly strandedCount: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* `/list` 的只读计划:一行 = 一组。释放量与 purge 用同一条口径——回收站目录与成员目录**现测**,
|
|
52
|
+
* 不用清册里记的 `sizeBytes`(那是删除那一刻的事实,盘上早就变了)。
|
|
53
|
+
*
|
|
54
|
+
* 盘上后代经 `selectStrandedMembers` 选出(排除全部清册 id、bare id 全局只算一次);目录不在的成员
|
|
55
|
+
* 不进 `members`(与 `planMemberRemovals` 同口径)。
|
|
56
|
+
*/
|
|
57
|
+
export declare function planVisibleTrash(deps: CoreDeps, rows: readonly TrashEntry[], groups: readonly TrashGroupView[]): Promise<VisibleTrashGroup[]>;
|
|
58
|
+
/** 一次永久删除的只读计划:哪些目录要删、各自实测多少字节、哪些会话要先摘归档集。
|
|
59
|
+
* `kind` 同时决定执行器在**删目录阶段**失败时交不交部分回执:`trash`(purge)不带、`orphan`
|
|
60
|
+
* (orphan-clean)带 `{removed, freedBytes, failedSessionId}`——回执与 `kind` 在生产里 1:1,
|
|
61
|
+
* 所以由 `kind` 派生,不另存一份会跟它漂移的字段;更早的 `unarchive` / `detach` 一步不套回执。 */
|
|
62
|
+
export interface RemovalPlan {
|
|
63
|
+
readonly kind: 'trash' | 'orphan';
|
|
64
|
+
readonly trash: readonly PlannedTrashRow[];
|
|
65
|
+
readonly members: readonly PlannedMemberRemoval[];
|
|
66
|
+
readonly unarchive: readonly string[];
|
|
67
|
+
readonly bytes: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* purge 的删除计划:`targets` 由调用方按组语义(`trash/groups.ts`)选好,这里只量、只筛、只查活体。
|
|
71
|
+
*
|
|
72
|
+
* - `trash` 按 targets 原序逐个实测(目录缺席的行 `present:false` / 0 字节,但清册行仍要摘)。
|
|
73
|
+
* - 盘上后代经 `selectStrandedMembers` 选出(一次问全部 targets、排除全部清册 id、bare id 全局只计划一次)。
|
|
74
|
+
* - `members` 只收盘上还有目录的成员(目录缺席没有可删的字节);`unarchive` = targets + 这些成员:
|
|
75
|
+
* 只摘这一次真要碰的 id。
|
|
76
|
+
* - `admission:'live'` 在量目录与任何写之前逐个查 targets 与**全部枚举到的**盘上后代;
|
|
77
|
+
* 任一在跑就整条拒绝,零副作用。
|
|
78
|
+
* - `sessionQuery` 缺席时端口回 `{ available: false }` ⇒ members 为空、不抛(盘上残留留给 `GET /orphans` 兜底)。
|
|
79
|
+
*/
|
|
80
|
+
export declare function planTrashRemoval(deps: CoreDeps, rows: readonly TrashEntry[], targets: readonly TrashEntry[], options: {
|
|
81
|
+
readonly admission: 'none' | 'live';
|
|
82
|
+
}): Promise<RemovalPlan>;
|
|
83
|
+
/**
|
|
84
|
+
* orphan-clean 的删除计划:成员是调用方扫出来的传递闭包(`orphanGroupsOf`)。
|
|
85
|
+
*
|
|
86
|
+
* - `members` 只收盘上还有目录的成员(目录缺席没有可删的字节),`bytes` 只算这些实测值。
|
|
87
|
+
* - `unarchive` 覆盖**全部传入成员**(含目录缺席):orphan-clean 在删目录之前整批摘归档集,
|
|
88
|
+
* 目录缺席的 id 也可能还挂在归档集里;重试时不会再长出一条幽灵 id。
|
|
89
|
+
* - live 准入覆盖**全部传入成员**(含目录缺席):它们都在这一组的可见面里,任一在跑就整组拒绝。
|
|
90
|
+
* - 回执由 `kind:'orphan'` 派生:删目录阶段失败时执行器要交回 `{removed, freedBytes, failedSessionId}`。
|
|
91
|
+
*/
|
|
92
|
+
export declare function planOrphanRemoval(deps: CoreDeps, members: readonly {
|
|
93
|
+
readonly sessionId: string;
|
|
94
|
+
readonly projectDir: string;
|
|
95
|
+
}[]): Promise<RemovalPlan>;
|
|
96
|
+
/**
|
|
97
|
+
* 按计划执行一次永久删除:只写、不再量、不再判活体(计划就是执行前的闸)。
|
|
98
|
+
*
|
|
99
|
+
* 顺序(与迁移前的 purge / orphan-clean 一致):整批摘归档集 → 摘有账本的成员的账本 → 逐条回收站行
|
|
100
|
+
* (在才删目录 → 摘清册行 → 通告成员离场)→ 逐条盘上成员(删目录 → 通告成员离场)。目录删掉就没有
|
|
101
|
+
* "退回去"这回事,中途失败**不回滚**;已经删掉的由下面的计数器如实交回。
|
|
102
|
+
*
|
|
103
|
+
* 失败形状沿用调用方原来的措辞与结构:
|
|
104
|
+
* - `kind:'orphan'`(orphan-clean)⇒ `io` + `{removed, freedBytes, failedSessionId}`,不伪装成整组没动;
|
|
105
|
+
* - `kind:'trash'`(purge)⇒ 同一个标签、不带 details。
|
|
106
|
+
* - orphan-clean 的 unarchive / detach 在旧实现里不包装,这里原样抛出(不改变现有错误形状)。
|
|
107
|
+
*
|
|
108
|
+
* 通告只经 `member-presence`(摘活体三态 + `api-session/removed`),不在这里另写一份。
|
|
109
|
+
*/
|
|
110
|
+
export declare function executeRemoval(deps: CoreDeps, plan: RemovalPlan): Promise<{
|
|
111
|
+
removed: number;
|
|
112
|
+
freedBytes: number;
|
|
113
|
+
}>;
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
1
|
+
import type { TrashEntry } from '../trash/entry.js';
|
|
2
|
+
import type { CoreDeps } from '../deps.js';
|
|
3
3
|
/**
|
|
4
4
|
* 彻底删除:从回收站里**真的**抹掉一条(或整组、或整站),并连带那些"还留在盘上、没被带走"的后代。
|
|
5
5
|
*
|
|
6
6
|
* 与另外两个动词的关系(ADR-0002):它的 interface 只有"一个条目 id(或缺席 = 清空)",
|
|
7
7
|
* 批量的快照与"已被同批前一条带走"的判据不在这里(归 `verbs/batch.ts`)。
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* **这条动词只做两件事:选目标、拿计划交给执行器**。量目录、筛盘上后代、活体准入与"先退归档集、
|
|
10
|
+
* 再摘账本、最后删目录"的顺序都住 `verbs/permanent-removal.ts`——计划只读,执行器只写,计划就是
|
|
11
|
+
* 执行前的闸(别在这里再长出一段手写步骤)。
|
|
12
|
+
*
|
|
13
|
+
* **这条动词不做回滚**:目录删掉就没有"退回去"这回事(2026-10-19 `f2a7757`:删到一半失败时已删目录不回滚;
|
|
10
14
|
* 带部分计数的 `details` 回执只属于 `orphan-clean`,purge 的 `removed` / `freedBytes` 仍只在成功回执里给)。
|
|
11
|
-
*
|
|
15
|
+
* 对应地,`kind:'trash'` 的计划失败时执行器只抛那一步的 `io` 与原文、不带 details。
|
|
12
16
|
*/
|
|
13
|
-
export declare function purgeTrash(deps:
|
|
17
|
+
export declare function purgeTrash(deps: CoreDeps): (entryId?: string,
|
|
14
18
|
/** **只读**清册快照:批量层已经读过一次就递下来(ADR-0002);收缩归批量层,动词不碰它。 */
|
|
15
19
|
snapshot?: readonly TrashEntry[]) => Promise<{
|
|
16
20
|
removed: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type TrashEntry } from '../trash/entry.js';
|
|
2
|
-
import { type
|
|
3
|
-
import type {
|
|
2
|
+
import { type HostIdentityPort } from '../ports/host-port.js';
|
|
3
|
+
import type { CoreDeps } from '../deps.js';
|
|
4
4
|
/**
|
|
5
5
|
* 恢复 = 把删除那次**按原路退回**,而且按组走:当年是按组一起搬进来的(父 + 它在盘上的孩子),
|
|
6
6
|
* 只回父就会在回收站里留下一堆点不到的孩子行——清单只列父行,那些行既看不见也清不掉。
|
|
@@ -11,14 +11,14 @@ import type { DeleteDeps } from './delete-session.js';
|
|
|
11
11
|
* 预检在写之前,是为了不让"父已经回到 `sessions/`、孩子因为项目目录没了而回不去"这种半组留在外面。
|
|
12
12
|
* **工作区账本不在这条硬前提里**:宿主的「删除工作区」只删注册、保留日志,记下的工作区没了就按
|
|
13
13
|
* 「未分组」收(判据在 {@link attachableWorkspaceId}),照旧回盘——恢复是加法,不该因为一个可选的账目而失败。
|
|
14
|
-
* ② **逐个恢复**,顺序与删除相反:文件先回来 → 挂账本
|
|
14
|
+
* ② **逐个恢复**,顺序与删除相反:文件先回来 → 挂账本 →(旧清单迁移)取消归档 → 摘清册行。
|
|
15
15
|
* ③ 中途失败时 journal 把这个成员自己退回回收站;**已经恢复完的**兄弟由整组 catch 按相反顺序一起退回。
|
|
16
16
|
*
|
|
17
17
|
* **通告不在这里**:一次批量只该拉一遍宿主会话表、只发一次 `api-session/added`(2026-10-17 那次
|
|
18
18
|
* "恢复很慢"就是逐条发)。通告归 `verbs/batch.ts`(ADR-0002),所以这个动词的 interface 只有
|
|
19
19
|
* "一个条目 id 进、回收站那一行出",没有批量专用的开关。
|
|
20
20
|
*/
|
|
21
|
-
export declare function restoreSession(deps:
|
|
21
|
+
export declare function restoreSession(deps: CoreDeps): (entryId: string,
|
|
22
22
|
/** **只读**清册快照:批量层已经读过一次就递下来,整批因此只读一次(ADR-0002)。
|
|
23
23
|
* 动词**不收缩**它——收缩与"已被同批前一条带走"的判据都归 `verbs/batch.ts`。 */
|
|
24
24
|
snapshot?: readonly TrashEntry[]) => Promise<TrashEntry>;
|
|
@@ -32,8 +32,8 @@ snapshot?: readonly TrashEntry[]) => Promise<TrashEntry>;
|
|
|
32
32
|
* 判据**只有这一处**:`memberRestore` 拿它决定挂不挂,`GET /list` 拿它决定行上那句「原工作区已不存在,
|
|
33
33
|
* 恢复后归入未分组」说不说。两边各问一遍就会有一天一个说、一个不挂。
|
|
34
34
|
*/
|
|
35
|
-
export declare function attachableWorkspaceId(host: Pick<
|
|
35
|
+
export declare function attachableWorkspaceId(host: Pick<HostIdentityPort, 'workspaceExists'>, entry: TrashEntry): Promise<string | undefined>;
|
|
36
36
|
/** 这一条记着的工作区**是不是已经没了**(区别于"删除时它就没有账目"的空串)——清单行据此决定
|
|
37
37
|
* 要不要在点之前说那句「原工作区已不存在,恢复后归入未分组」。由 {@link attachableWorkspaceId}
|
|
38
38
|
* 派生,不另起一份判据:那样会有一天一个说、一个不挂。 */
|
|
39
|
-
export declare function isWorkspaceMissing(host: Pick<
|
|
39
|
+
export declare function isWorkspaceMissing(host: Pick<HostIdentityPort, 'workspaceExists'>, entry: TrashEntry): Promise<boolean>;
|