DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

jiulanyanyue-boop /

jiulanyanyue-boop/dsh-archive-manager

Verified

DSH(DeepSeek Harness)归档会话管理插件:按工作区分组列出所有归档会话,显示归档时间、最后活动时间与占用体积;可一键恢复回原位置,或彻底删除本地存储(含会话历史、投影缓存、工作区记账与 live 会话),不留幽灵残留、无需刷新页面。

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@b40a96f4

归档会话管理 · archive-manager

给 DeepSeek Harness (DSH) 装一个真正的「归档中心」:按工作区分组看清所有归档会话,一键恢复回原位,或彻底抹掉本地存储 —— 不留幽灵行、不留点不开的会话、不用重启。

简体中文 · English

License: MIT Platform: DSH Web Version No build step PRs Welcome

归档会话管理


这是什么

DSH 自带的「归档」只是一个隐藏开关:把会话从侧边栏藏起来,仅此而已。

  • 你看不到自己归档了多少个、占了多大空间、属于哪个工作区;
  • 想找回一个三个月前的会话,得先把侧边栏里所有会话翻一遍;
  • 想把没用的归档会话彻底清掉腾空间,DSH 没有这个功能;
  • 更糟的是:删过存储文件之后,侧边栏还会留着点开就报 ENOENT 的幽灵会话。

archive-manager 把这些补齐了:在 设置 → 归档会话管理 里给你一整页,把「归档」从单向的隐藏操作,变成可看、可恢复、可彻底删除的完整生命周期管理。

纯前端 + Host 路由,零构建、零 npm 依赖、零外部服务,装完重启一次即可使用。


它解决了哪些真问题

这一页不是把 API 套个壳,而是逐条堵住了归档会话长期存在的坑:

问题 真实表现 本插件的做法
归档内容不可见 归档 = 从侧边栏消失,剩下什么也不知道 按工作区分组列出:标题 / 归档时间 / 最后活动 / 占用体积 / 文件是否存在,一眼看清
归档时间无处可查 DSH 只持久化「归档 id 集合」,不存归档时间 插件自建索引 archive-times.json,首次观测到归档即记录,原子写、恢复/删除时同步清理
恢复找不到「原来在哪」 只能翻侧边栏猜 恢复走 unarchiveSession,工作区记账原样保留,会话精确回到原工作区原位置
删完还剩幽灵行 删除文件后侧边栏仍列着它、点开仍在、发消息报 ENOENT 删除时先 workspace/session-stop 停活动 → detachEntered 摘掉 live 会话 → 再删磁盘 → detachSession 清记账 → 摘归档集合
删除只删了一半 文件没了但工作区记账还在,侧边栏永远挂着一条打不开的记录 删除语义改为「抹掉这个会话的全部本地痕迹」,磁盘 / 记账 / 归档集合 / 时间索引四者收干净
界面残留要手动刷新 删完还得关设置页重开 本地先摘行 + ctx.sessions.refresh() + 带序号对账,页面内即时生效
刷新竞态把删掉的行复活 并发 /state 响应乱序,旧数据覆盖新状态 /state 请求带序号单飞,过期响应直接丢弃
历史残留无人清理 磁盘上没文件、记账里还有,越积越多 POST /repair + 启动 3 秒静默自检(幂等),页面发现残留时也会弹出提示条一键清理

功能一览

能力 说明
设置页整页入口 设置 → 归档会话管理,走宿主预留的 settings.section(id archived-sessions,order 25,排在「Agent 预设」之后,图标是归档盒而非默认齿轮)
按工作区分组 每组显示工作区标题 + 目录名 + 条数;已不属于任何工作区的会话单独归入「未归组会话」
每行信息完整 完整标题(不截断,长标题换行)、归档时间(绝对 + 相对)、最后活动时间、创建时间、占用体积;存储缺失时标红提示
恢复 立即取消归档,会话回到原工作区原位置;不需要刷新页面即可在侧边栏看到
永久删除 二次确认(显示将删除的项数与体积)→ 停活动 → 摘 live 会话 → 删磁盘 → 清记账 → 摘归档 → 清索引
失效引用清理 自动 + 手动双通道;清理只动记账,不碰任何现存会话文件
悬停出按钮 「恢复 / 删除」默认隐藏,鼠标悬停或键盘聚焦时平滑淡入;触屏设备常显 —— 列表干净,又不牺牲可发现性
主题完全跟随 配色、字体、间距、圆角全部引用宿主变量(--dsw-alias-* / --dsw-radius-*),浅色、深色、任意皮肤下都不跑偏
中英双语 词典随宿主 locale 服务切换,不是硬编码文案
可访问性 role="dialog" / aria-labelledby / Esc 关闭 / 焦点管理 / 键盘可达
空状态也有温度 没有归档会话时是一块鲸鱼装饰,而不是冷冰冰的「无数据」

截图

列表:按工作区分组,信息密度刚刚好

悬停显示操作按钮

永久删除:二次确认,说清楚删掉多少

永久删除二次确认

空态

空态与鲸鱼装饰


安装

前置条件

项 要求
DSH Web / 桌面端,0.2.1-rc.2 上验证通过(依赖 webServer、workspaceRegistry、sessions 三个服务)
Node >= 22.19.0(DSH 自带运行时即可,无需自行安装)
构建 不需要。仓库里就是可直接运行的产物

⚠️ 先读这条:不要用裸包名安装

本仓库的包名是 archive-manager,但 archive-manager 与 dsh-archive-manager 这两个名字在 npm 上都已被别人占用。DSH 的「添加插件」会把裸包名当作 npm 包去解析,于是:

你填 实际装到 结果
archive-manager 别人的 npm 包 ❌ 词不达意,且版本大概率不兼容当前 DSH
dsh-archive-manager 别人的 npm 包(peer 要求 0.1.0-rc.6) ❌ 报 Plugin ... is incompatible with dsh 0.2.1-rc.2
https://github.com/jiulanyanyue-boop/dsh-archive-manager 本仓库 ✅ 正解

结论:请填完整 GitHub 地址,别填裸包名。

方式一:GitHub 链接(推荐)

打开 设置 → 插件 → 添加插件,填入:

https://github.com/jiulanyanyue-boop/dsh-archive-manager

几种等价写法(由 DSH 安装器解析,都会克隆本仓库):

写法 说明
https://github.com/jiulanyanyue-boop/dsh-archive-manager 最直观,直接粘地址
github:jiulanyanyue-boop/dsh-archive-manager pnpm 的 GitHub 简写
https://github.com/jiulanyanyue-boop/dsh-archive-manager#v1.2.0 固定到某个 tag / 分支 / commit(需该 tag 已推送,见「开发与发布」)
git+https://github.com/jiulanyanyue-boop/dsh-archive-manager.git 显式 git 协议

安装器会先做一次 git ls-remote 连通性检查(默认 5 秒超时),再交给 pnpm 克隆安装。

装完请重启一次 DSH 桌面应用。 profile 组合在启动时一次性构建(未开启 HMR),插件条目需要重启才生效;之后的所有操作都在页面内即时生效,不再需要重启或手动刷新。

方式二:本地目录 / tarball(离线场景)

# 在仓库目录里打一个 tarball
npm pack --pack-destination "$env:USERPROFILE\Downloads"

然后在「添加插件」里填 tarball 的绝对路径,或直接填解包后的目录绝对路径。 「安装源」下拉只对 npm 包名生效,填本地路径不会联网。

打 tarball 前请确认 package.json 的 files 白名单包含你需要的文件; GitHub 安装是整仓克隆,不受 files 限制,只有 npm pack 会受。

方式三:手动挂载到 profile

  1. 把仓库目录放到 <DSH_HOME>/plugins/archive-manager
  2. 编辑 <DSH_HOME>/profiles/<your-profile>/package.json:
    • dependencies 里加 "archive-manager": "link:<DSH_HOME>/plugins/archive-manager"
    • dsh.profile.bundles 末尾加 "archive-manager"
  3. 重启 DSH

同一个包只装一次。 archive-manager 既是包名也是 Loader 条目 id,装两份会出现重复条目。 换来源时请先把旧的一条依赖 + bundles 项删掉。


使用

归档一个会话

归档入口由 DSH 自带(会话列表里的「归档」),本插件不改变原有行为。 归档后的会话会从侧边栏消失,并出现在「设置 → 归档会话管理」里。

恢复

在列表里悬停目标行 → 点「恢复」。

  • 会话立刻取消归档,回到它原来的工作区、原来的位置;
  • 侧边栏无需刷新即可看到;
  • 页面顶部出现「已恢复「标题」,会话列表已刷新」提示。

永久删除

悬停 → 点「删除」→ 二次确认 → 「永久删除」。

确认框会明确告诉你将删除几项存储、大约多少体积。确认后按固定顺序执行:

  1. workspace/session-stop —— 并行停下该会话的回合、子代理、后台任务、提醒;
  2. detachEntered —— 把 live 会话从 SessionStore 摘掉,等 session/disposed 的清理落地;
  3. 删除会话目录 + 投影缓存文件(失败则整体失败、不摘任何记账);
  4. workspace.detachSession —— 清工作区记账;
  5. unarchiveSession —— 摘归档集合;
  6. 清归档时间索引。

不会进回收站,无法撤销。

清理失效引用

若检测到「记账里有、磁盘上没有」的历史残留,页面顶部会出现提示条:

发现 N 条失效的会话引用 …… 「一键清理」

清理只 detachSession 记账,不会删除任何现存会话文件。插件启动 3 秒后也会静默自检一次(幂等,正常情况下什么也不做)。


兼容性

项 状态
DSH 0.2.1-rc.2 ✅ 已验证(本插件开发与测试基线)
DSH 0.1.0-rc.x ⚠️ 未验证,且大概率不可用(该时期的客户端/宿主服务形态与现在不同)
Host 服务缺失时 插件不激活,不会渲染一个假列表
本地化 中文 / English,跟随宿主 locale

说明:本插件的 package.json 没有声明 peerDependencies,也没有 engines.dsh 字段 —— DSH 的兼容性预检对「未声明要求」的插件一律放行,实际兼容性由运行时的服务探测决定(缺服务即不激活)。


架构

插件是 Host 半 + 浏览器半 两件套,和 boot-splash、dsh-purge 等现有 DSH 插件同构。

文件组成

文件 作用
host.js Host 侧:注册 /plugins/archive-manager/* 路由、读写索引、执行恢复/删除
client.js 浏览器侧:window.__ModuleLoader__.load() 形态,注册设置页 settings.section
cordis.patch.yml bundle patch 层:向宿主声明一条已启用的 Loader 条目
package.json 包清单:dsh.bundle.patch 指向 patch,dsh.client.platform = web

Host 半(host.js)

inject = ['webServer', 'workspaceRegistry', 'sessions']

注册 5 条 exact 路由(刻意不用 prefix —— prefix 会吃掉 client.js 的静态物化路径):

方法 路径 作用
GET /plugins/archive-manager/ping 自检({ ok, plugin })
GET /plugins/archive-manager/state 整棵归档列表(分组 + orphanCount,组内按归档时间倒序)
POST /plugins/archive-manager/restore { sessionId } 恢复
POST /plugins/archive-manager/delete { sessionId } 永久删除
POST /plugins/archive-manager/repair 清理失效记账(幂等)

数据来源:

  • 归档集合与工作区记账:ctx.workspaceRegistry(archivedSessionIds / list())
  • 标题、创建时间、最后活动:<DSH_HOME>/storages/session_projcache/sessions/<id>.json
  • 存储体积与存在性:<DSH_HOME>/sessions/<workspace-slug>/<session-id>/
  • 归档时间:<DSH_HOME>/archive-manager/archive-times.json(自建索引,原子写,上限扫描 20000 条会话)

并发控制:恢复 / 删除 / 清理共用同一条 Promise 串行队列,任何时刻只有一个变更在跑。

浏览器半(client.js)

  • 无构建步骤,require('react') 由宿主模块表提供,不用 JSX(React.createElement 直接构建);
  • 注册 settings.section:{ id: 'archived-sessions', order: 25, label, locale, inject };
  • 数据流:createStore(不可变快照 + 订阅)→ useStore(useState + useEffect)→ 重渲染;
  • 样式以 <style data-plugin-css> 注入,全部引用宿主 CSS 变量;圆点/胶囊类控件显式 corner-shape: round,避开宿主全局 superellipse 对圆形的影响;
  • 刷新链路:本地先摘行 → ctx.sessions.refresh() → /state 带序号对账;并订阅 ctx.workspaces 的归档集合变化,其它页签或外部操作也会触发本页对账;
  • 生命周期:所有 setInterval / addEventListener / store 订阅 / slot 注册都在 useEffect 清理函数或 ctx.effect 里释放。

接口示例

BASE=http://127.0.0.1:<port>/plugins/archive-manager

curl $BASE/state
curl -X POST $BASE/restore -H 'content-type: application/json' -d '{"sessionId":"session-xxxx"}'
curl -X POST $BASE/delete  -H 'content-type: application/json' -d '{"sessionId":"session-xxxx"}'
curl -X POST $BASE/repair

返回码约定:

码 error 字段 含义
200 — 成功
400 invalid-session-id / 请求体解析失败原因 请求体不合法
403 host-not-allowed(/ping) Host 不是本机回环
403 untrusted-request(/state)/ foreign-origin(其余) 来源校验未通过
404 not-archived 恢复时该会话不在归档列表中
404 session-not-found 删除时本地已无任何痕迹(可安全重复调用)
405 method-not-allowed 方法不对(如对 /delete 用 GET)
409 session-active 仍有回合 / 子代理 / 后台任务在跑,拒绝删除
500 delete-failed / internal 磁盘删除失败(记账保持原样)/ 未预期异常
503 registry-unavailable Workspace 注册表尚未就绪
503 activity-probe-failed / session-stop-failed 无法确认活动状态 / 停不下来 → 取消删除

安全设计

这个插件能递归删除会话存储,所以删除入口按「宁可拒绝,不可误删」来写:

面 做法
请求来源 路由由 webServer 直接提供(不过 /api 的浏览器信任栅栏),因此自加两道闸:Host 必须是本机回环(挡 DNS rebinding / 局域网调用;桌面端 IPC 桥接不带 Host 时放行)+ Origin 必须同源(挡跨站请求)
sessionId 校验 白名单正则 ^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$ —— 故意不允许 .,于是 ..、../../x、a/b、C:\x 全部在入口被拒;另有一层冗余字符检查
路径边界 任何要删的路径都必须落在 sessions/ 或投影缓存根目录之内(path.relative 判定),越界直接不碰
删除前置条件 会话必须仍连着「磁盘 / 工作区记账 / 归档集合」三者之一才允许删;活动探测失败 → 503 取消删除;需停活动但停不下来 → 503 取消删除(绝不在「可能还在跑」的状态下盲删)
响应内容 /state、/ping 不返回 home 绝对路径、不返回工作区全路径(只给目录名 pathLabel)、不返回原始 id 列表;/delete 不返回被删的绝对路径,只给 removedCount 与失败项的 basename
请求体 上限 16 KiB,超限直接拒
权限模型 插件跑在宿主进程内,拥有与宿主相同的文件权限;可删范围仅限当前 DSH_HOME 下的会话存储,路由端口只监听回环。不要把 DSH 的 web 服务绑到局域网地址对外暴露。

已知限制

  • 归档时间是近似值:对「插件首次运行之前就已归档」的会话,只能记成首次观测时刻 —— DSH 本身不持久化该时间。
  • 附件不随会话删除:<DSH_HOME>/attachments 是内容寻址存储、可能被多个会话共享,且不含会话 id,因此不随单个会话清理。
  • 有活动工作时不删:「仍有回合 / 子代理 / 后台任务在跑」的会话会被拒绝(409),需先让它停下 —— 与 DSH 归档准入策略一致。
  • 需要两个 Host 服务:缺 workspaceRegistry 或 webServer 时插件不激活。
  • 网络盘误清风险:启动自检按「磁盘上是否存在会话目录」判断失效引用;会话目录若挂在暂时不可用的网络盘上,可能被误清记账(只影响侧边栏归属,不删任何文件,重新打开会话会自动挂回)。
  • 仅 Web 侧:dsh.client.platform = web,暂不提供其它客户端形态。

FAQ / 故障排查

Q:装上后设置页没有「归档会话管理」? 重启一次 DSH。profile 组合在启动时构建,插件条目不会热加载。

Q:安装时报 Plugin ... is incompatible with dsh 0.2.1-rc.2? 你填的是裸包名 dsh-archive-manager,装到了 npm 上别人的包。改填完整 GitHub 地址。

Q:点删除后侧边栏还留着那个会话? 请先用较新的 DSH 版本(SessionStore.detachEntered 是较新的公开原语,越老的宿主越可能没有)。查看 /delete 响应里的诊断字段: probe.sessionStore(Host 能否访问 SessionStore)、probe.liveAtDelete(删除时会话是否活着)、detachedLive(是否成功摘除)。 若 sessionStore: false,说明宿主未暴露该服务,此时请重启 DSH 让会话列表重新拉取。

Q:删除提示 该会话还有工作在运行? 先在该会话里停止正在进行的回合/子代理,再回来删。这是刻意的保护,不是 bug。

Q:能在多台机器间同步归档状态吗? 不能。归档集合由 DSH 的 WorkspaceRegistry 本地持久化,本插件只读它、不引入额外同步。

Q:会不会误删别的数据? 删除范围被三重限制:sessionId 形状白名单 → 路径必须落在 sessions/ 或投影缓存根内 → 失败时整体回滚记账。落在边界外的路径一律不碰。


开发与发布(作者侧)

仓库根目录就是包根目录(package.json / cordis.patch.yml / host.js / client.js 都在根), 所以推上去就能直接装 —— 不要塞进 packages/xxx 子目录。

# 一条命令:校验白名单 → 提交 → 打 tag → 推 main 与当前 tag
./publish-github.ps1 -RepositoryUrl https://github.com/<your-name>/dsh-archive-manager

publish-github.ps1 的安全约束:

  • 只 git add 显式白名单里的文件,绝不 git add -A;
  • 工作区出现白名单外改动直接停下(需 -AllowUnexpectedFiles 才继续);
  • 不覆盖已有 origin(需 -ForceOrigin);
  • 只推当前版本对应的那一个 tag,不 push --tags;
  • 只允许在 main 上发布。

GitHub 安装时要注意的三点

  1. 仓库根 = 包根。安装器把链接当包地址,不会去找子目录。
  2. 不需要构建步骤。host.js / client.js 都是可直接运行的产物,包里没有 prepare / build 脚本,pnpm 克隆后不会跑编译(避免因缺 devDependencies 装失败)。
  3. files 白名单:目前为 host.js、client.js、cordis.patch.yml、README.md、screenshots/*.png (LICENSE 与 README.md 由 npm 自动纳入)。 .git、.backup、node_modules 不会进包。

    想换成全新的宣传截图时,记得同步更新 files 里的图名白名单(或保留 screenshots/*.png 通配)。

本地开发

无构建链。改完 host.js / client.js 后重启 DSH 即可生效(Host 与浏览器两侧都会重新加载)。

调试时推荐用 /plugins/archive-manager/ping 确认路由已挂载,再用 /state 看分组数据是否符合预期。


贡献

欢迎 Issue / PR。改动涉及删除逻辑时,请一并说明:

  • 你验证过的 DSH 版本;
  • 删除前后的 /state 输出;
  • 侧边栏在删除后是否残留(以及 /delete 返回的诊断字段)。

许可证

MIT © archive-manager contributors


与 DeepSeek 官方无隶属关系,这是一个社区插件。鲸鱼只是恰好路过 🐳

—/ 5

No ratings yet

Verified DSH bundle

Commit b40a96f4f871

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout