@mzzsfy/dsh-session-manager 0.3.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 ADDED
@@ -0,0 +1,82 @@
1
+ # @mzzsfy/dsh-session-manager
2
+
3
+ DeepSeek Harness 会话生命周期管理插件:自动归档 + 归档面板 + 归档删除 + 回收站还原重挂载 + 历史输入浮层。
4
+
5
+ ## 功能
6
+
7
+ - 历史输入浮层:输入焦点处按 `Alt+↑` 唤起浮层(平时界面零占位),浏览并回填历史输入,浮层内 `←/→` 切换范围:范围序为 **常用 → 当前会话(默认落点)→ 本工作区 → 全部工作区**,`→` 向更大范围,`←` 返回收藏,边界停住;范围显示为浮层左上角徽标。**工作区持久缓存**:每工作区一个 JSON 文件(`~/.dsh/historyPrompt/<工作区>-<路径哈希>.json`,可辨认 + 防同名冲突),内容为该工作区聚合后的输入条目(带 `sid` 来源会话溯源)。浮层请求直接读缓存文件立即返回(毫秒级,响应 `{ inputs, aligned }`);**对齐**在后台进行:解压范围内最近会话产物(经官方 `sessionQuery.readSession`,仅 `source.kind === 'user'` 的人类输入,工具结果回填与插件注入排除)、与缓存合并去重后原子写回(临时文件 + 改名)。对齐时机:插件启动对齐最近会话覆盖的工作区、每次浮层请求触发(同工作区 `HISTORY_ALIGN_THROTTLE_MS` 节流)、**运行中会话参与对齐(输入实时追加)**。范围语义:`prompts` 用户显式收藏的常用提示词(全局单文件 `prompts.json`,不按工作区,详见收藏交互);`session` 该会话输入(缓存按 `sid` 过滤);`workspace` 同 cwd 工作区缓存;`global` 全部工作区缓存并集。上限:全部历史最多保留最新 `HISTORY_INPUT_LIMIT` 条、单条截 `HISTORY_INPUT_MAX_CHARS` 字符,聚合精确文本去重保留最新时间。首次(该工作区尚无缓存文件)`aligned=false`,client 显示「首次对齐历史中」提示并每 `HISTORY_REPULL_MS` 静默重拉;单会话产物读取失败仅告警跳过;scope 非法或缺省回退 `session`。client 半区挂官方 `conversation.input.dock` 插槽(渲染为零高度锚点);条目点选或 `↑/↓` 选择(高亮行带左侧色条、自动滚入可视区)、`←/→` 切换范围、`Enter` 填入、`Esc`/外点关闭(捕获阶段拦截,先于 Lexical 光标移动;IME 组合中跳过);浮层与输入框同宽对齐、不透明实底,选中态高亮强化;回填一律走宿主公共契约 `inputActions.setDraft`(不直改编辑器 DOM)。宿主缺该插槽或 `inputActions` 缺失时本功能整体不注册不渲染,快捷键与浮层均不存在,不影响其余能力。
8
+ - 常用提示词收藏:`prompts` 以外的范围,历史行鼠标悬停时行尾出现收藏星标(已收藏实星、未收藏空心),点击即收藏/取消(经 `POST /api/session-manager/prompts/toggle`),toast 反馈并同步星标;`prompts` 范围右上角「编辑」按钮进入编辑态:行内文本框直接改(Enter/失焦保存,实现为移除旧文本 + 收藏新文本)、行尾 `×` 删除、底部输入框 Enter 新增,「完成」退出;上限 `HISTORY_PROMPTS_MAX` 条,超出裁掉最旧;收藏与自动对齐的历史缓存互不覆写(`listWorkspaceCaches` 跳过 prompts.json);client 与 core 的 `HISTORY_SCOPES` 镜像由 parity 测试锁定。
9
+ - 历史浮层启停开关:低频功能,归档面板末行小尺寸开关(规约 switch 形态 `sm-histsw`,状态选择器锚定 `input[type=checkbox]`);值存宿主 settings(`historyEnabled`,默认启用,原生设置页与本面板同存储即时同值),读写经本插件 `GET/POST /api/session-manager/history-enabled`(client 写 settings 不经宿主 remotes,零版本脆弱依赖);浮层挂载拉取一次,停用即锚点/快捷键/浮层整体不渲染、键盘监听放行,变更刷新页面生效。
10
+ - 自动归档:host 半区对超期会话走官方 `workspace.archiveSession` 通道,三个触发源共用同一评估与门闩:新会话创建(`session/created`,按该会话所属工作区限定)、settings 就绪后的启动补扫(全量,清掉停机期间积压)、每日周期轮(全量,经宿主 timer 服务固定短 tick + 到期判断)。幂等:已归档会话不参与评估。阈值 `autoArchiveDays` 默认 7,`0` 关闭;周期间隔 `autoArchiveIntervalHours` 默认 24,`0` 关闭周期轮,变更经周期 tick 对账(关闭即时暂停、重启用最迟下个 tick 生效、缩短经锚定钳制前移,最长等新间隔而非等满旧周期)。评估筛选:createdAt 纯内存预筛 + 已归档跳过 + stat 后活跃度判定,locate 缺失(第三方后端)与产物不可读的会话一律跳过,宁可漏归档不可误归档。经 settings 命名空间 `session-manager` 注册(schema 拒绝负数与非整数)。timer 为软依赖:宿主定时服务不可用时仅周期轮停用,面板顶部提示,插件其余能力不受影响。
11
+ - 归档面板:设置页「会话归档」分区,数据为 client 侧 `session.list` 行 ∩ `workspaces.follow` 归档快照的交集,按更新时间倒序;行内支持取消归档与删除。
12
+ - 归档与操作通知:host 归档动作经 `workspace.follow` 的 `archived` 增量帧到达 client,集合差分得到新增条数 N,经公共通知依赖 `@mzzsfy/dsh-toast` 顶部居中显示「有 N 个会话已归档」;面板操作(恢复 / 删除 / 重新挂载等)的成功与失败反馈同样经该依赖展示,失败提示常驻待确认。dsh-toast 为普通 npm 依赖随本插件安装,其宿主占位条目由本插件 cordis.patch.yml 代挂。
13
+ - 删除:仅对已归档会话生效(运行中守卫先于执行,执行前 TOCTOU 复检,运行中的会话不可删除;OS 回收存在数百 ms 异步窗口,复检通过后仍可能恢复运行——此时回收已完成,响应附警告并落服务端日志),两段式确认(展示标题 / 日志体积,产物已缺失时以「产物已丢失」替代体积)后按 locate → trash → 台账 → detach → 归档清理单序执行;同 id 并发删除仅首个生效,其余以「正在删除中」拒绝。会话产物目录整体移入系统回收站(Windows PowerShell VisualBasic / macOS Finder / Linux gio;Windows 路径经环境变量传入 PowerShell,含空格或特殊字符的路径安全),可还原,不做直接删除降级。trash 成功即写入已删除台账(独立 storage domain `session_manager`,读改写经进程内互斥链串行化且单次操作带超时兜底,条目上限 200 裁最旧),记录会话 id 与产物原位置。产物**目录**已缺失的会话,仅当已归档或台账有记录(同 id 重删的残留收尾)时跳过回收与台账、仅解除列表关联,提示「产物已不存在,已完成列表清理」;两者皆无的缺失可能是新建会话尚未落盘,直接拒绝以防剥离活会话。
14
+ - 已删除分区与重挂载:面板「已删除」区列出台账条目(标题 / 原位置 / 删除时间)。用户在系统回收站将会话文件夹还原到原位置后点「重新挂载」,经官方 `workspace.attachSession` 挂回工作区列表并清除台账;「移除记录」幂等清除单条。还原动作本身始终由用户在系统回收站完成,插件不驱动系统回收站。
15
+
16
+ ## 回收站还原与重新挂载
17
+
18
+ 删除移入系统回收站的是**会话产物目录**,「原位置」形如 `C:\Users\<你>\.dsh\sessions\--<工作区路径编码>--\<会话id>\`(工作区目录名由宿主对 cwd 做编码,非裸路径;目录内是 `session.jsonl.zstd` 日志)。辨认以面板「已删除」区记录的原位置为准,无需理解编码规则。
19
+
20
+ > 0.1.3 版本删除的条目回收的是日志**文件** `session.jsonl.zstd` 而非目录:还原该文件即可(目录本身未被移除),还原后同样走「重新挂载」。
21
+
22
+ 还原步骤(系统回收站操作):
23
+
24
+ - Windows:打开桌面「回收站」→ 按「原位置」列(含 `.dsh\sessions\`)或名称(会话 id)定位目录 → 右键「还原」。
25
+ - macOS:打开 Finder「废纸篓」→ 选中会话目录 → 右键「放回原处」。
26
+ - Linux(GNOME Files):打开「回收站」→ 右键「还原」;命令行 `gio trash --restore`。
27
+
28
+ 还原后回到面板「已删除」区点「重新挂载」:会话经官方通道挂回工作区,重新出现在会话列表。注意事项:
29
+
30
+ - 未还原(持久层读不到产物)时重挂载直接拒绝,提示先还原。
31
+ - 还原后重挂载提示「未找到会话所属工作区」:插件按会话 cwd 匹配工作区失败,通常是原工作区目录已删除或更名。
32
+ - 清空回收站后产物永久丢失,台账条目仅剩记录价值,应「移除记录」。
33
+ - 只还原产物而不重挂载:数据在磁盘上,但会话不会自动回到工作区列表(删除时已 detach)。
34
+
35
+ ## 失败矩阵
36
+
37
+ | 失败点 | 表现 |
38
+ |--------|------|
39
+ | locate 返回 undefined(SQLite 等后端) | 拒绝执行,提示后端不支持,无副作用 |
40
+ | 产物目录已缺失(且已归档或台账有记录) | 跳过归档资格 / 回收 / 台账,仅 detach 与归档清理,提示「产物已不存在,已完成列表清理」;清理半失败转 partial 并聚合失败点,重试即补全 |
41
+ | 产物目录已缺失(未归档且无台账记录) | 拒绝执行(可能是新建会话尚未落盘,剥离活会话属破坏性误删),无副作用 |
42
+ | trash 失败 | 整体中止,提示失败,目录与台账未动,可重试 |
43
+ | trash 成功、detach 失败 | 视为已删除,提示「已移入回收站,但移除列表记录失败」;还原前重试将走产物缺失路径完成列表清理(台账保留),或还原后走「已删除」区重挂载 |
44
+ | trash 成功、归档清理失败 | 已删除但归档集合残留,提示「已移入回收站,但移除归档记录失败」;经取消归档重试清理(幂等) |
45
+ | trash 成功、台账写入失败 | 已删除,提示「已移入回收站,但重挂载记录失败」,其余步骤照常完成 |
46
+ | 重挂载、产物未还原 | 拒绝,提示先到系统回收站还原,无副作用 |
47
+ | 重挂载、无匹配工作区 | 拒绝,提示未找到会话所属工作区,无副作用 |
48
+ | 重挂载、attachSession 失败 | 拒绝并透出原始错误,台账保留供重试 |
49
+ | 重挂载、挂载后台账清除失败 | 挂载已生效,提示 partial「已重新挂载,但清除台账记录失败」,经「移除记录」收尾 |
50
+ | trash 执行期间会话恢复运行 | 回收已完成,响应附警告「回收期间会话恢复运行」并落服务端日志;建议检查会话状态(agent 写入已断裂) |
51
+ | 台账操作超时(存储域挂起) | 单次读改写超 10s 按失败降级(同「台账写入失败」),互斥链不死锁,后续操作可重试;超时写操作后台落盘仍安全(幂等语义) |
52
+
53
+ 多个失败点并发时按 detach > 归档清理 > 台账的优先级聚合透出:前两者的 partial 消息末尾追加「,且重挂载记录失败」。
54
+
55
+ ## 已知取舍
56
+
57
+ - 取消归档:官方 workspace registry 明确归档为 one-way,无移除 API。本插件经 `storageDomain.get('workspace')` 的 global 句柄直写 `archivedSessionIds`(写入经 `domain/changed` 驱动 follow 帧),并把注册表进程内快照 `registry.state` 同步为写后值——注册表只在自身写路径同步该快照,不同步则其后续全量写回与 `workspace.list` 重连基线会复活刚移除的 id,官方归档的幂等判定也会因旧快照静默跳过(即早期版本「取消归档后列表不消失 / 二次归档不出现」的根因)。合并 durable 与快照取并集后再移除:可自愈历史失同步与清理半失败(经取消归档重试即补全),代价是快照中的陈旧 id 会在任一次清理时随全量写回重新落盘,可经再次取消归档清除。`registry.state` 为上游内部字段,缺失即路由报错 loud fail(注册表未就绪或上游形态变更)。域 global 仅支持整体写回,读改写窗口若与注册表两阶段变更交错,理论上可回退其 pendingMutation/workspaceIds 中间态,下次启动校验将 loud fail;同理,恢复操作与进行中的自动归档评估并发时,评估携带的旧快照整包写回也可能复活刚移除的 id,再次恢复即可清除——窗口极窄且域 API 无原子原语可用,属已知取舍。
58
+ - 删除:成功路径在 detach 后同样从归档集合移除该 id(域与快照同步),清理失败响应 partial 提示;detach 失败时不清理归档集合,保留归档资格供重试。删除后 `session.list` 的会话行按官方语义仅在宿主发出 `session/disposed`(经 `api-session/removed`)时移除;官方 `SessionStore` 无按 id dispose 的公开 API,本进程内打开过的会话被删除后,其列表行会以「未分组」形式残留,直至宿主重启(重启后 live 记录清空,持久层扫描因产物缺失自然不再列出)。残留行仍可再次执行删除:产物缺失路径即为此设计,完成列表关联清理并提示。重挂载复用该语义:删除后会话行短暂残留在 client 会话模型,「已删除」区标题在重连前显示原标题,重连后回退会话 id。
59
+ - 已删除台账:独立 storage domain `session_manager`(global 单列表),非 workspace 域、非审计层——存在意义仅为重挂载定位产物原位置。trash 成功即记录(位于 detach 前),台账失败仅降级重挂载便利,不回滚删除;同 id 再次删除替换旧条目。台账读改写经进程内互斥链串行化(并发删除不再有丢更新窗口),条目上限 200、超出裁最旧,防无界增长写放大。台账不随产物还原自动清除,以「重新挂载」或「移除记录」收尾;清空回收站后的残留条目无恢复价值,应手动移除。
60
+ - 评估的活跃时间:JSONL 后端以产物 mtime 作为最近活跃代理,updatedAt = max(createdAt, mtime);非 JSONL 后端退化为 createdAt。评估两级筛选:先用 createdAt 纯内存预筛(mtime 只会增大 updatedAt,createdAt 未超期必不超期),仅对预筛存活者做产物 stat / blank 探测,活跃会话零 IO。空白判定:live 会话 seq=0,冷会话以 JSONL 产物「仅 header 一行」判定,locate 不可用的后端按非空白处理。评估整体带超时兜底(宿主服务挂起时门闩必然复位,不会永久停摆);单会话归档失败仅告警不中断整轮。
61
+ - 无批量操作、无内容搜索、无会话详情预览。
62
+ - 自动归档评估门闩:评估进行中其他触发源(含周期轮与 session/created)的新触发直接丢弃,不做排队;漏掉的会话由下一次触发兜底,启动补扫与每日周期轮保证了积压会话最迟一个周期内归档。产物不可读(mtime 探测失败)的会话视为已删除,不参与归档,防止删除后的会话被重新归档复活。timer 软依赖:宿主定时服务缺失或调用失败时周期轮停用,设置页显示降级提示(session/created 触发与启动补扫不受影响);timer 服务晚于插件激活时周期轮自动补武装。
63
+ - 归档提示以「连续两个 ready 快照」为差分启用条件:基线首装(启动与重连)不提示存量,重连基线携带的离期新增仍会提示。通知展示经公共依赖 `@mzzsfy/dsh-toast`(external require),本包不再自带通知 UI。client.js 为单文件自包含格式,守卫逻辑与 core.mjs 各存一份镜像,修改需两处同步(projectRows / archiveToastStep / projectDeletedRows 同规);test/parity.test.mjs 对各组镜像做行为级对照并锁定 client 侧确认态文案与 host MESSAGES 同值。client 已删除列表加载失败时保留旧数据并 console.warn,不渲染成「无记录」。路由错误响应:业务错误原样透传中文文案,系统级错误(带 fs 错误码,message 内嵌绝对路径)收敛为固定文案并落服务端日志。
64
+ - 历史输入的已知取舍:对齐扫描各工作区最近 `HISTORY_SESSION_SCAN_LIMIT` 个会话(更早会话的输入不入缓存),解压发生在后台、永不阻塞浮层响应,代价是首次对齐期间列表为空、需等静默重拉;**解压不重复执行**:每会话提取结果持久化在工作区缓存 `extracts` 段并附产物 stat 指纹(mtimeMs+size),对齐时先 stat 比对、产物未变零解压,判断完全基于磁盘、跨重启生效;运行中会话(当前会话)提取结果只保留内存不落盘——产物持续变化,落盘指纹立即失效;启动零解压(历史直接读磁盘缓存,重启前的输入本就在 entries 里),全量对齐延迟 `HISTORY_STARTUP_DELAY_MS` 再跑且只回溯最近 `HISTORY_STARTUP_SCAN_LIMIT` 个会话覆盖的工作区;对齐中连续解压占用超 `HISTORY_ALIGN_SLICE_MS` 即让出 `HISTORY_ALIGN_YIELD_MS`(zstd 解压为同步 CPU 操作,不设让出会让宿主启动阻塞数十秒);超 `HISTORY_ALIGN_MAX_ARTIFACT_BYTES` 的巨产物跳过自动对齐(单次 readSession 内部同步解压不可让出,实时性让位于不卡主循环);header 查找走 ctx 级 TTL 缓存(inputs 路由不每次全量扫描 listSessions);对齐为双车道:批量车道(窗口对齐)与焦点车道(单会话实时追加)各自串行互不等待,会话范围请求检测到产物指纹失配即触发焦点对齐并返回 aligned=false;浮层打开期间固定节奏轮询当前范围(数据可能晚于首次响应到达,一次性重拉预算会让迟到数据永不出现);单会话首条数据可见预算 3s:会话范围路由触发焦点对齐后就地等待 `HISTORY_FOCUS_WAIT_MS`(2s),正常会话单次请求内拿到新数据,超时(巨产物)走轮询流式补齐;不解压搬进 worker:产物为多帧 zstd + 帧扫描 + 记录解码 + 版本协商,`readSession` 深度耦合宿主持持层,worker 内复刻等于维护第二份产物解析实现,宿主升级即漂移;缓存上限 `HISTORY_INPUT_LIMIT` 条,超出裁掉最旧(超长会话史会丢早期输入);新输入从发送到浮层可见有秒级延迟(宿主批量刷盘 200ms + 焦点对齐 + 轮询节奏),非严格实时;缓存文件为明文 JSON(输入内容落盘 `~/.dsh/historyPrompt`,与产物本身同级敏感);单条超长文本(大段粘贴)在 host 侧截断,回填与展示均用截断后文本;交互收敛为快捷键唤起浮层(`Alt+↑`,无 mac 系统占用,与编辑器光标移动无冲突),无常驻界面元素。
65
+ - 重挂载的并发窗口:attachSession 后、台账清除前进程中断,残留条目重挂载时因官方 attachSession 幂等(已在 sessionIds 中则跳过校验直写)无副作用,再次点按或「移除记录」即可收尾。台账域打开失败时已删除 / 重挂载 / forget 以 400 拒绝;删除路由走 partial 降级(其余步骤照常,提示「已移入回收站,但重挂载记录失败」),不做无台账中断——产物进回收站后中断删除只会造成状态不一致。
66
+ - 测试基建:trash 为进程级唯一 OS 副作用出口,经 `executor.trashPath` 注册表注入,删除全流程(trash 成败 / 台账成败 / 归档清理)已有路由层覆盖。
67
+
68
+ ## 验证
69
+
70
+ ```sh
71
+ npm test
72
+ ```
73
+
74
+ 纯逻辑层(评估状态机 / 删除资格与失败矩阵 / 面板投影 / 归档差分 / 空白判定 / 回收站命令构造)以 `node --test` 覆盖,无外部依赖。路由层测试依赖 peer 包可解析,仓库根未安装依赖时自动 skip,`npm install` 后激活。Windows 真实回收站执行测试仅在本平台执行,其余平台自动 skip。周期评估测试经 `mock.timers` 接管 `setInterval` 与 `Date`(显式传 `now`:接管后虚拟时钟从 epoch 起算,夹具时间戳会全成「未来」),timer 服务以 makeCtx 桩模拟激活与缺失两种形态。
75
+
76
+ ## 开发安装(不经 npm 发布直接装仓库副本)
77
+
78
+ ```sh
79
+ dsh plugin --profile web add file:./packages/dsh-session-manager
80
+ ```
81
+
82
+ `file:` 安装指向仓库工作副本,改代码后重跑该命令即同步,无需发版。
@@ -0,0 +1,12 @@
1
+ # session-manager 打包补丁:将自动归档 + 归档面板 + 回收站删除插件以单条目
2
+ # 注入 profile 根。由 `dsh plugin add @mzzsfy/dsh-session-manager` 应用;
3
+ # 行 id 指向本插件宿主半区,其 /api/session-manager/* 路由服务设置页中的浏览器半区。
4
+ # dsh-toast 行代挂公共通知依赖的宿主占位(该包无自带 patch,作为普通依赖随本
5
+ # 插件装载,其 client 由此进入客户端模块表供 external require);条目 id 带本
6
+ # 插件前缀避免多消费插件同时安装时树内 id 冲突,name 才是模块表的包解析键。
7
+
8
+ - insert:
9
+ - id: session-manager
10
+ name: '@mzzsfy/dsh-session-manager'
11
+ - id: session-manager-dsh-toast
12
+ name: '@mzzsfy/dsh-toast'
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@mzzsfy/dsh-session-manager",
3
+ "description": "会话自动归档与管理:超期自动归档、归档面板、删除进系统回收站、还原后一键重挂载",
4
+ "version": "0.3.1",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js",
9
+ "./client": "./src/client.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "dsh": {
13
+ "bundle": {
14
+ "patch": "./cordis.patch.yml"
15
+ },
16
+ "client": {
17
+ "platform": "web",
18
+ "external": [
19
+ "@mzzsfy/dsh-toast/client"
20
+ ]
21
+ }
22
+ },
23
+ "scripts": {
24
+ "test": "node --test \"test/*.test.mjs\"",
25
+ "npmPublish": "npm publish --access public --provenance=false --registry=https://registry.npmjs.org"
26
+ },
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/mzzsfy/dsh-plugin.git"
31
+ },
32
+ "engines": {
33
+ "node": ">=22"
34
+ },
35
+ "dependencies": {
36
+ "@mzzsfy/dsh-toast": "^0.1.2"
37
+ },
38
+ "peerDependencies": {
39
+ "@deepseek-ai/dsh-settings": ">=0.1.2-alpha.2",
40
+ "@deepseek-ai/dsh-storage-domain": ">=0.1.1-rc.2",
41
+ "@deepseek-ai/schemastery": ">=3.18.0",
42
+ "react": "^18.2.0",
43
+ "zod": ">=4.5.4"
44
+ },
45
+ "files": [
46
+ "src",
47
+ "test",
48
+ "cordis.patch.yml",
49
+ "README.md"
50
+ ]
51
+ }