dsh-session-ops 0.2.0 → 0.2.1

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 CHANGED
@@ -7,7 +7,7 @@ One package, one host-plugin row, two halves:
7
7
 
8
8
  | Half | What it does | Entry points |
9
9
  | --- | --- | --- |
10
- | delete | filter by workspace / archive / subagent, batch select, per-session guards; removes data from disk | HTTP `/session-admin/api/*`, model tool `session_admin`, right-pane "会话管理" tab, conversation-header trash icon, settings page "会话工具" |
10
+ | delete | filter by ungrouped / temp / archive / subagent, batch select, per-session guards; removes data from disk | HTTP `/session-admin/api/*`, model tool `session_admin`, right-pane "会话管理" tab, conversation-header trash icon, settings page "会话工具" |
11
11
  | move | relocate the log, rewrite `header.cwd`, follow workspace membership; optional memory follow (off by default) | HTTP `/session-move/api/*`, model tool `session_move`, right-pane "会话归位" tab, session context menu |
12
12
 
13
13
  The session-storage primitives live in this package under `lib/store/` (project-directory key
@@ -49,10 +49,10 @@ The plugin row has one shared `enabled` master switch; every other key is indepe
49
49
 
50
50
  | Key | Default | Meaning |
51
51
  | --- | --- | --- |
52
- | `enabled` | `true` | master switch; `false` registers no routes, tools or slots |
53
- | `root` | `''` | session root override; empty derives it from `$DSH_HOME/sessions` |
52
+ | `enabled` | `true` | master switch; `false` registers no host routes or tools (the browser half still loads its tabs) |
53
+ | `root` | `''` | session root override; empty reads `sessionPersistence.root` (`$DSH_HOME/sessions` for the jsonl backend) |
54
54
  | `adminAllowHosts` | `[]` | delete-half LAN trust list (parsed from the `Host` header) |
55
- | `moveAllowHosts` | `[]` | move-half LAN trust list (exact socket `remoteAddress` match) |
55
+ | `moveAllowHosts` | `[]` | move-half LAN trust list (exact `Host` header match) |
56
56
  | `headerDeleteButton` | `true` | conversation-header trash icon (icon + two confirmations) |
57
57
  | `allowWorkspaceSessions` | `false` | allow deleting sessions that belong to a workspace |
58
58
  | `allowLiveSessions` | `false` | allow deleting sessions still loaded in the host |
@@ -62,10 +62,11 @@ The plugin row has one shared `enabled` master switch; every other key is indepe
62
62
  | `memoryFollow` | `off` | project-memory follow: `off` / `copy` / `move` (`move` is irreversible) |
63
63
  | `repairForkChildrenOnBoot` | `true` | re-file fork children whose membership was lost, at boot |
64
64
 
65
- The two trust keys **cannot** be merged: the delete half parses the `Host` header and additionally
66
- rejects `sec-fetch-site: cross-site` and cross-origin `Origin`, while the move half matches the
67
- socket address exactly. Merging them would loosen one half. Both only affect LAN access; loopback is
68
- always trusted.
65
+ The two trust keys **cannot** be merged: the delete half decides loopback from the `Host` header and
66
+ matches `adminAllowHosts` as a `host` or `host:port` authority, while the move half decides loopback
67
+ from the socket's `remoteAddress` and matches `moveAllowHosts` against the exact `Host` value. Both
68
+ reject `sec-fetch-site: cross-site` and cross-origin `Origin`; merging them would change one half's
69
+ observable behaviour. Both only affect LAN access, and only loopback is trusted by default.
69
70
 
70
71
  The browser half registers one config card on the Plugins page: slot `plugins.bundle.config`, key =
71
72
  the package name `dsh-session-ops`, carrying the seven volatile knobs (4 delete + 3 move). Saving
package/README.zh.md CHANGED
@@ -1,16 +1,15 @@
1
1
  # dsh-session-ops
2
2
 
3
- DeepSeek Harness(DSH)的**会话运维插件**:真删除会话、把会话搬到另一个工作区,并把工作区成员关系修好。
3
+ DeepSeek Harness(DSH)的会话运维插件:真删除已持久化的会话,把会话搬到另一个工作区,并同步修好工作区成员关系。
4
4
 
5
5
  一个包、一个插件行,包含两个半边:
6
6
 
7
7
  | 半边 | 能力 | 入口 |
8
8
  | --- | --- | --- |
9
- | 删除 | 按工作区 / 归档 / 子代理筛选、批量选择、逐条守卫;真删磁盘数据 | HTTP `/session-admin/api/*`、模型工具 `session_admin`、右栏「会话管理」页签、会话标题栏垃圾桶、设置页「会话工具」 |
9
+ | 删除 | 按未分组、临时或失效目录、归档、子代理筛选;批量选择;逐条守卫;真删磁盘数据 | HTTP `/session-admin/api/*`、模型工具 `session_admin`、右栏「会话管理」页签、会话标题栏垃圾桶、设置页「会话工具」 |
10
10
  | 搬迁 | 搬日志、改写 header 的 `cwd`、跟随工作区成员表;可选项目记忆跟随(默认关) | HTTP `/session-move/api/*`、模型工具 `session_move`、右栏「会话归位」页签、会话右键菜单 |
11
11
 
12
- 会话存储原语(项目目录键编解码、`session[.vN].jsonl[.zstd]` 帧读写、工作区注册表、
13
- `$DSH_HOME` 与文件日志、HTTP 底座)收在本包的 `lib/store/`,两个半边共用同一份实现。
12
+ 会话存储原语收在本包的 `lib/store/`:项目目录键编解码、`session[.vN].jsonl[.zstd]` 帧读写、工作区注册表、`$DSH_HOME` 与文件日志、HTTP 底座。两个半边共用同一份实现。
14
13
 
15
14
  ## 安装
16
15
 
@@ -18,37 +17,32 @@ DeepSeek Harness(DSH)的**会话运维插件**:真删除会话、把会话
18
17
  dsh plugin --profile <profile> add dsh-session-ops
19
18
  ```
20
19
 
21
- 装好后重启宿主(或按 DSH 的热加载规则让 profile 重组)。插件行由包内
22
- `cordis.patch.yml` 声明,entry id 是 `session-toolbox`。
20
+ 装好后重启宿主,或按 DSH 的热加载规则让 profile 重组。插件行由包内 `cordis.patch.yml` 声明,entry ID 是 `session-toolbox`。
23
21
 
24
- ## ⚠️ 破坏性删除
22
+ ## 破坏性删除
25
23
 
26
- 「删除」是**真删除**,不是归档:
24
+ 「删除」是真删除,不是归档。三处数据一起从磁盘移除:
27
25
 
28
- - `<DSH_HOME>/sessions/<项目目录键>/<session-id>/`(会话日志)
29
- - `<DSH_HOME>/storages/session_projcache/sessions/<session-id>.json`(投影缓存)
30
- - `<DSH_HOME>/rewind-snapshots/<session-id>/`(回退快照,若有)
26
+ - `<DSH_HOME>/sessions/<项目目录键>/<session-id>/`:会话日志
27
+ - `<DSH_HOME>/storages/session_projcache/sessions/<session-id>.json`:投影缓存
28
+ - `<DSH_HOME>/rewind-snapshots/<session-id>/`:回退快照(若有)
31
29
 
32
- 三处一起从磁盘移除,并顺手清理因此变空的项目目录。**没有回收站,删了无法恢复。**
33
- 删除前请自行备份 `$DSH_HOME`;面板提供预演与二次确认,但最终责任在操作者。
30
+ 删除后顺手清理因此变空的项目目录。没有回收站,删了无法恢复;删除前请自行备份 `$DSH_HOME`。面板提供预演与二次确认,但最终责任在操作者。
34
31
 
35
- 默认安全边界(可在配置里改):`allowWorkspaceSessions=false`、`allowLiveSessions=false`、
36
- `refuseRunning=true` —— 工作区会话、正在跑的会话、运行中的搬迁默认都被拒绝。
32
+ 默认安全边界(可在配置里改):`allowWorkspaceSessions=false`、`allowLiveSessions=false`、`refuseRunning=true`。工作区会话、正在跑的会话、运行中的搬迁默认都被拒绝。
37
33
 
38
- 搬迁不是删除:日志目录从旧 project 目录整体移到新目录,`header.cwd` 改写,工作区
39
- 成员表跟着变;0.2.2+ 内核里 `session.lock` 会一起搬走(inode 不变),目标目录已有
40
- 租约时直接拒绝,不会制造「锁在旧目录、日志在新目录」的半套状态。
34
+ 搬迁不是删除:日志目录从旧 project 目录整体移到新目录,`header.cwd` 改写,工作区成员表跟着变。内核 0.2.2+ 的会话目录里有 `session.lock`,搬迁时会一起搬走(inode 不变);目标目录已有租约时直接拒绝,不会留下「锁在旧目录、日志在新目录」的半套状态。
41
35
 
42
36
  ## 配置
43
37
 
44
- 插件行只有一个 `enabled` 总开关,两半共用;其余键各自独立:
38
+ 插件行只有一个 `enabled` 总开关,两个半边共用;其余键各自独立:
45
39
 
46
40
  | 键 | 默认 | 作用 |
47
41
  | --- | --- | --- |
48
- | `enabled` | `true` | 总开关;`false` 时不注册任何路由、工具、槽位 |
49
- | `root` | `''` | 会话根目录;空表示用 `$DSH_HOME/sessions` |
50
- | `adminAllowHosts` | `[]` | 删除半边的 LAN 信任列表(按 `Host` 头解析 host/hostname 匹配) |
51
- | `moveAllowHosts` | `[]` | 搬迁半边的 LAN 信任列表(按 socket `remoteAddress` 精确匹配) |
42
+ | `enabled` | `true` | 总开关;`false` 时宿主不注册路由与工具(浏览器侧页签仍会加载) |
43
+ | `root` | `''` | 会话根目录;空则取 `sessionPersistence.root`(jsonl 后端为 `$DSH_HOME/sessions`) |
44
+ | `adminAllowHosts` | `[]` | 删除半边的 LAN 信任列表(按 `Host` 头解析 `host` 或 `host:port`) |
45
+ | `moveAllowHosts` | `[]` | 搬迁半边的 LAN 信任列表(按 `Host` 头完整值精确匹配) |
52
46
  | `headerDeleteButton` | `true` | 会话标题栏垃圾桶图标(图标 + 两步确认) |
53
47
  | `allowWorkspaceSessions` | `false` | 允许删除已归属工作区的会话 |
54
48
  | `allowLiveSessions` | `false` | 允许删除宿主里驻留的会话 |
@@ -58,36 +52,29 @@ dsh plugin --profile <profile> add dsh-session-ops
58
52
  | `memoryFollow` | `off` | 项目记忆跟随:`off` / `copy` / `move`(`move` 不可逆) |
59
53
  | `repairForkChildrenOnBoot` | `true` | 启动时补挂漏记账的 fork 子会话 |
60
54
 
61
- 两个信任键**不能合并**:删除半边按 `Host` 头并拒绝 `sec-fetch-site: cross-site` 与
62
- 跨源 `Origin`,搬迁半边按 socket 地址精确匹配;合成一个等于放宽其中一边。两者都只
63
- 影响 LAN 访问,loopback 始终被信任。
55
+ 两个信任键不能合并:删除半边按 `Host` 头解析回环 authority,`adminAllowHosts` 可写 `host` 或 `host:port`;搬迁半边按 socket 的 `remoteAddress` 判断回环,`moveAllowHosts` 只认 `Host` 头的完整值。两边都拒绝 `sec-fetch-site: cross-site` 与跨源 `Origin`,合并会改掉其中一边的对外行为。两者都只影响 LAN 访问,默认只信回环。
64
56
 
65
- 浏览器侧还有一处指向本行的配置卡片:槽 `plugins.bundle.config`,key 是包名
66
- `dsh-session-ops`,7 个 volatile 旋钮(删除 4 + 搬迁 3)保存即写回 profile 的
67
- `cordis.patch.yml`,无需重启。
57
+ 浏览器侧还有一处指向本行的配置卡片:槽 `plugins.bundle.config`,key 是包名 `dsh-session-ops`,含 7 个 volatile 旋钮(删除 4 + 搬迁 3)。保存即写回 profile 的 `cordis.patch.yml`,无需重启宿主。
68
58
 
69
59
  ## 兼容区间
70
60
 
71
61
  - Node.js `>=24`
72
62
  - DSH `^0.2.1-rc.2 || ^0.2.2-alpha.2`
73
63
 
74
- 会话右键菜单需要内核提供 `@deepseek-ai/dsh-client-ui-context-menu`(0.2.2+);没有这个
75
- 服务时只少两个菜单项,页签、工具与 HTTP 入口照旧。搬迁时携带 `session.lock`、
76
- 启动期 fork 子会话补记账同样以 0.2.2+ 的持久化实现为准。
64
+ 会话右键菜单需要内核提供 `@deepseek-ai/dsh-client-ui-context-menu`(0.2.2+)。没有这个服务时只少两个菜单项,页签、工具与 HTTP 入口照旧。搬迁时携带 `session.lock`、启动期 fork 子会话补记账,同样以 0.2.2+ 的持久化实现为准。
77
65
 
78
66
  ## 排障产物
79
67
 
80
68
  两份文件日志保留各自原有的行格式(历史产物,刻意不统一):
81
69
 
82
- - `$DSH_HOME/logs/dsh-session-admin.log` —— `[时间] 级别 正文`
83
- - `$DSH_HOME/logs/dsh-session-move.log` —— `时间 [级别] 正文`
70
+ - `$DSH_HOME/logs/dsh-session-admin.log`:`[时间] 级别 正文`
71
+ - `$DSH_HOME/logs/dsh-session-move.log`:`时间 [级别] 正文`
84
72
 
85
- 搬迁与自愈的关键行:`membership repair mounted`、`membership: attached fork child …`、
86
- `membership: attach failed …`、`membership sweep: re-attached N of M fork child(ren) …`。
73
+ 搬迁与自愈的关键行:`membership repair mounted`、`membership: attached fork child …`、`membership: attach failed …`、`membership sweep: re-attached N of M fork child(ren) …`。
87
74
 
88
75
  ## 作为库使用
89
76
 
90
- `lib/store/` 与插件生命周期无关、零 `@deepseek-ai/*` 依赖,可以单独引用。包里提供两种入口:
77
+ `lib/store/` 与插件生命周期无关,零 `@deepseek-ai/*` 依赖,可以单独引用。包里提供两种入口:
91
78
 
92
79
  ```js
93
80
  // 根入口(与合并前的会话存储共享库公开面一致)
@@ -105,10 +92,7 @@ npm run build # 宿主 tsc(src/ -> lib/、lib/types/)、浏览器 tsc(
105
92
  npm test # 先 build,再用 node --test 跑 test/**/*.test.ts(Node ≥24 原生执行 TS)
106
93
  ```
107
94
 
108
- 手写代码现在全是 TypeScript:宿主在 `src/`,浏览器半边在 `client/`(给
109
- `window.__ModuleLoader__` 用的经典脚本 IIFE,按单文件发射、不打包)。
110
- `lib/**/*.js` 与 `lib/types/` 是随仓库入库的构建产物(checkout / profile 安装不先 build 也能用);
111
- `test/*.ts` 由 Node 直接执行,不参与发射。
95
+ 手写代码全部是 TypeScript:宿主在 `src/`,浏览器半边在 `client/`(给 `window.__ModuleLoader__` 用的经典脚本 IIFE,按单文件发射、不打包)。`lib/**/*.js` 与 `lib/types/` 是随仓库入库的构建产物,checkout 或 profile 安装不先 build 也能用;`test/*.ts` 由 Node 直接执行,不参与发射。
112
96
 
113
97
  ## License
114
98
 
package/cordis.patch.yml CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # 合并包:一个插件行同时提供原先两个插件的能力。
4
4
  # - 删除(原 dsh-session-admin):HTTP /session-admin/api,模型工具 session_admin,
5
- # 右栏「会话管理」页签,会话标题栏垃圾桶图标,设置页「会话清理」卡片。
5
+ # 右栏「会话管理」页签,会话标题栏垃圾桶图标,设置页「会话工具」卡片。
6
6
  # - 搬迁(原 dsh-session-move):HTTP /session-move/api,模型工具 session_move,
7
7
  # 右栏「会话归位」页签(含左栏底部入口)。
8
8
  # 两个半边共用本行的这一份配置;插件页上本行的「配置」卡片就是合并后的那张(7 个旋钮)。
package/docs/DETAIL.md CHANGED
@@ -4,19 +4,21 @@ Turns the session-to-workspace binding into an explicit tool: really delete sess
4
4
  between workspaces while keeping the registry consistent.
5
5
 
6
6
  ## Two right-pane tabs
7
- - Delete: filter by workspace, archive or subagent; batch select; running sessions refused by default.
7
+ - Delete: filter by ungrouped, temp, archived or subagent; batch select; running sessions refused by default.
8
8
  - Move: relocate the log, rewrite header cwd, follow workspace membership; optional memory follow (off).
9
9
 
10
10
  ## Other entry points
11
11
  - Session context menu: move / delete.
12
12
  - Model tools session_admin, session_move; host HTTP /session-admin/api, /session-move/api.
13
13
 
14
- ## Shared storage primitives (`lib/store`)
15
- - `paths.js`: project-directory key codec (`projectKey` / `encodeSegment`), session and generation file naming.
16
- - `frames.js`: `session[.vN].jsonl[.zstd]` frame scanning, header read (two strictness levels), cwd rewrite.
17
- - `registry.js`: workspace membership and archive sets, resident sessions, mid-turn detection, write-handle redirection.
18
- - `host.js`: `$DSH_HOME`, best-effort file logging, volatile config unwrapping.
19
- - `http.js`: shared JSON response / request-body plumbing and the prefixed route skeleton.
14
+ ## Shared storage primitives
15
+
16
+ Sources live in `src/store/*.ts` and are built to `lib/store/*.js`:
17
+ - `paths.ts`: project-directory key codec (`projectKey` / `encodeSegment`), session and generation file naming.
18
+ - `frames.ts`: `session[.vN].jsonl[.zstd]` frame scanning, header read (two strictness levels), cwd rewrite.
19
+ - `registry.ts`: workspace membership and archive sets, resident sessions, mid-turn detection, write-handle redirection.
20
+ - `host.ts`: `$DSH_HOME`, best-effort file logging, volatile config unwrapping.
21
+ - `http.ts`: shared JSON response / request-body plumbing and the prefixed route skeleton.
20
22
 
21
23
  ## Notes
22
24
  - A move carries session.lock (0.2.2+ write lease) and empties the source directory; it refuses when the target already holds a lease.
package/docs/DETAIL.zh.md CHANGED
@@ -1,23 +1,29 @@
1
1
  # 会话运维
2
2
 
3
- 把 DSH 的「会话 → 工作区」绑定关系做成可操作的工具:真实删会话、把会话搬到另一个工作区,并把成员关系修好。
3
+ 把 DSH 的「会话 → 工作区」绑定关系做成可操作的工具:真删除会话、把会话搬到另一个工作区,并修好成员关系。
4
4
 
5
5
  ## 两个页签
6
- - 删除:按工作区、归档、子代理筛选,批量选择;运行中会话默认拒绝。
7
- - 搬迁:列出会话与归属,选择目标工作区后搬日志、改 header cwd、跟随注册表成员;支持记忆条目跟随(默认关)。
6
+
7
+ - 删除:按未分组、临时或失效目录、归档、子代理筛选,支持批量选择;运行中的会话默认拒绝。
8
+ - 搬迁:列出会话与归属,选择目标工作区后搬日志、改 header 的 `cwd`、跟随注册表成员;支持项目记忆跟随(默认关)。
8
9
 
9
10
  ## 其他入口
10
- - 会话右键菜单:移动会话到工作区…、删除会话…
11
- - 模型工具 session_admin、session_move;宿主 HTTP /session-admin/api、/session-move/api。
12
11
 
13
- ## 共享存储原语(`lib/store`)
14
- - `paths.js`:项目目录 key 编解码(projectKey / encodeSegment)、会话目录与 generation 文件名规则。
15
- - `frames.js`:`session[.vN].jsonl[.zstd]` 帧扫描、header 读取(两种严格度)、cwd 改写。
16
- - `registry.js`:工作区成员表 / 归档集合、驻留会话、「正在跑一轮」判定、写入句柄重定向。
17
- - `host.js`:`$DSH_HOME`、尽力而为的文件日志、volatile 配置解包。
18
- - `http.js`:JSON 响应 / 请求体读取底座与前缀路由骨架。
12
+ - 会话右键菜单:移动会话到工作区…、删除会话…
13
+ - 模型工具 `session_admin`、`session_move`;宿主 HTTP `/session-admin/api`、`/session-move/api`。
14
+
15
+ ## 共享存储原语
16
+
17
+ 源码在 `src/store/*.ts`,构建后是 `lib/store/*.js`:
18
+
19
+ - `paths.ts`:项目目录 key 编解码(`projectKey` / `encodeSegment`)、会话目录与 generation 文件名规则。
20
+ - `frames.ts`:`session[.vN].jsonl[.zstd]` 帧扫描、header 读取(两种严格度)、cwd 改写。
21
+ - `registry.ts`:工作区成员表与归档集合、驻留会话、「正在跑一轮」判定、写入句柄重定向。
22
+ - `host.ts`:`$DSH_HOME`、尽力而为的文件日志、volatile 配置解包。
23
+ - `http.ts`:JSON 响应与请求体读取底座、前缀路由骨架。
19
24
 
20
25
  ## 注意
21
- - 搬迁会把 session.lock 一起搬走(0.2.2+ 写租约),源目录清空;目标已有租约时拒绝。
22
- - 启动时会做一次 fork 子会话的定向补记账(repairForkChildrenOnBoot,默认开)。
23
- - 删除是永久性的:没有回收站、无法恢复,操作前请备份 `$DSH_HOME`。
26
+
27
+ - 搬迁会把 `session.lock` 一起搬走(内核 0.2.2+ 写租约),源目录清空;目标已有租约时拒绝。
28
+ - 启动时会做一次 fork 子会话的定向补记账(`repairForkChildrenOnBoot`,默认开)。
29
+ - 删除是永久性的:没有回收站、无法恢复;操作前请备份 `$DSH_HOME`。
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "dsh-session-ops",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "description": "Session operations for DeepSeek Harness: really delete persisted sessions (workspace/archive/subagent filters, running-session guards) and move sessions between workspaces (log relocation, header.cwd rewrite, workspace registry follow). Ships the shared session-store primitives (project-directory keys, jsonl.zstd frames, workspace registry, host/HTTP plumbing) as lib/store. One host entry with two HTTP prefixes and two model tools, one browser bundle with two right-pane tabs and a merged config card.",
8
+ "description": "Session operations for DeepSeek Harness: really delete persisted sessions (ungrouped/temp/archive/subagent filters, running-session guards) and move sessions between workspaces (log relocation, header.cwd rewrite, workspace registry follow). Ships the shared session-store primitives (project-directory keys, jsonl.zstd frames, workspace registry, host/HTTP plumbing) as lib/store. One host entry with two HTTP prefixes and two model tools, one browser bundle with two right-pane tabs and a merged config card.",
9
9
  "keywords": [
10
10
  "dsh",
11
11
  "dsh-plugin",