DSH Plugins Marketplace

DSH Plugins

Plugins

/

Development & Infrastructure

/

dsh-archive-manager

j

dsh-archive-manager

Identified★ 1

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

归档会话管理 · 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 关闭 / 焦点管理 / 键盘可达
空状态也有温度没有归档会话时是一块鲸鱼装饰,而不是冷冰冰的「无数据」

截图

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

悬停显示操作按钮

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

永久删除二次确认

空态

空态与鲸鱼装饰


安装

前置条件

项要求
DSHWeb / 桌面端,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-managerpnpm 的 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.jsHost 侧:注册 /plugins/archive-manager/* 路由、读写索引、执行恢复/删除
client.js浏览器侧:window.__ModuleLoader__.load() 形态,注册设置页 settings.section
cordis.patch.ymlbundle 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—成功
400invalid-session-id / 请求体解析失败原因请求体不合法
403host-not-allowed(/ping)Host 不是本机回环
403untrusted-request(/state)/ foreign-origin(其余)来源校验未通过
404not-archived恢复时该会话不在归档列表中
404session-not-found删除时本地已无任何痕迹(可安全重复调用)
405method-not-allowed方法不对(如对 /delete 用 GET)
409session-active仍有回合 / 子代理 / 后台任务在跑,拒绝删除
500delete-failed / internal磁盘删除失败(记账保持原样)/ 未预期异常
503registry-unavailableWorkspace 注册表尚未就绪
503activity-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 服务绑到局域网地址对外暴露。

自动更新与 Star 引导

插件自带升级能力,设置页里有「插件升级」卡片:

  • 三个版本:运行版本(本进程启动时加载的)、磁盘版本(当前文件)、最新版本(GitHub 最新 semver tag)
  • 检查更新:走 GitHub 公开 API,Host 侧缓存 6 小时;页面「检查更新」按钮强制刷新
  • 立即升级:按安装形态选路径 ——
    • 目录里有 .git:git fetch --tags + git reset --hard + git checkout --detach <tag>
    • 没有 .git:下载 tag 源码包解压覆盖(保留 .git / node_modules / var 等用户数据)
  • 重启提示:升级只改磁盘,运行中的代码不会变,所以卡片会显示「代码已更新,重启 DSH 后生效」
  • 去 GitHub 点 Star:调系统默认浏览器打开仓库页;只接受 https://github.com/...,不接受任意 URL

要有更新源,package.json 里必须写真实仓库地址(repository);占位符 YOUR_GITHUB_USER 会被识别为「无更新源」, 卡片会如实显示而不是假装检查过。

两个插件各自独立实现这套能力(各有一份 update/status、update/apply、open-repo), 互不 import、不共享文件或状态,只共用「行为约定」这一层。

已知限制

  • 归档时间是近似值:对「插件首次运行之前就已归档」的会话,只能记成首次观测时刻 —— 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 官方无隶属关系,这是一个社区插件。鲸鱼只是恰好路过 🐳

Comments

Loading…

From the same category

awesome-dsh-plugin

by awesome-dsh-plugin

A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表

Development & Infrastructure

★ 21.1k

CC0-1.0

Python

Oct 26, 2026

Index only — not installable

by 0xsline

DeepSeek Harness (DSH) ecosystem: curated plugins, tools, and infrastructure from dsh-external/hub and the public dsh-plugin topic.

Development & Infrastructure

★ 1.3k

CC0-1.0

Python

Oct 16, 2026

Index only — not installable

by Yuuyuko-uu

DSH 鱼的记忆:给会话一份会淡忘的长期记忆,每条都带时间

Development & InfrastructureMemory & ContextSessions & MessagesManifest valid

★ 300

MIT

JavaScript

Oct 27, 2026

dsh plugin --profile web add dsh-fish-memory

by pax-beehive

Open-source CLI, schemas, resolver, and DSH agent tools for DSH Plugin Hub

Development & Infrastructure

★ 277

MIT

TypeScript

Oct 20, 2026

Index only — not installable

by xiajiajun516

DeepSeek Harness (DSH) backup & restore plugin — export, import, migrate and sync your complete DSH configuration, plugins, MCP servers, skills and workspace. One-click migration to another machine.

Development & InfrastructureManifest valid

★ 255

MIT

TypeScript

Oct 25, 2026

dsh plugin --profile web add dsh-config-manager

by yjh051108

推荐组件(非必须):DeepSeek Harness 运行时注入器;已随 dsh-routing-suite 单仓库化保留,本仓库继续维护/发布。

Development & InfrastructureManifest valid

★ 167

TypeScript

Oct 16, 2026

dsh plugin --profile web add @dsh-external/dsh-super-injector