🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI
广告☁️ 云服务器特惠阿里云首购 8 折 · 腾讯云合作特惠
DeepSeek Harness Hub
← 返回列表

kira905/dsh-butler-archive

DeepSeek Harnessspec-screened扫描:中风险在 GitHub 查看 ↗
⚠ 装前注意

一个 DeepSeek Harness DSH Web 插件:在设置页新增「归档会话管理」分栏,用来查看 / 预览 /

基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/20 · 已提供中文文档

Unofficial DSH plugin: archive, browse, restore and delete idle sessions from the sidebar — zero dependencies. 非官方 DSH 插件:把闲置会话归档、浏览、恢复、删除,零依赖。

综合分
29.8
GitHub 分
29.8
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add kira905/dsh-butler-archive
未发布到 npm registry,仅可从源码安装,改用 GitHub 源安装
信任档位:已验证本站已于 1 天前真实安装成功
是什么
dsh 原生插件 · browser
装得上吗
本站已真实安装成功(非静态推断)
安全吗
本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
还在维护吗
活跃:最近一次提交在 5 天前

档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →

🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/22(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-archive-sessions(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖要求 >=0.1.1-rc.2 <0.2.0 · 最新 ? 兼容
✓入口文件main/exports/bin 已声明

未发布到 npm registry,仅可从源码安装

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/22 00:10:39

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

由 DeepSeek 最新模型翻译生成
dsh-archive-sessions

English · 中文(默认)

一个 DeepSeek Harness (DSH) Web 插件:在设置页新增「归档会话管理」分栏,用来查看 / 预览 /
恢复 / 删除那些被物理移出 sessions 目录的老会话。

它管理的是目录级归档——会话目录被整体搬到 /_archived-sessions///,
因而不再出现在侧边栏、也不再被主进程解码(这是它能显著降低启动/加载开销的原因)。
注意:这不同于 DSH 自带的「GUI 归档」——后者只是给会话打 archivedSessionIds 标记,
文件仍留在 sessions 目录里。

- host 半:注册一组 loopback-only HTTP 路由(默认前缀 /api/dsh-archive-sessions):

| 方法 | 路径 | 作用 |
|---|---|---|
| GET | {prefix}/config | 公开配置(界面文案 / 阈值,不含任何绝对路径) |
| GET | {prefix}/list | 列出归档会话 |
| GET | {prefix}/detail | 解码单个会话尾部 N 条消息 |
| POST | {prefix}/restore | 两段式恢复回 sessions |
| POST | {prefix}/delete | 物理删除归档会话 |
| GET | {prefix}/auto | 读取自动归档配置与上次结果 |
| POST | {prefix}/auto | 更新自动归档配置 |
| POST | {prefix}/auto/run | 立即执行一次自动归档(默认试跑) |

- client 半:设置页分栏 UI(按工作目录分组、行内预览、恢复、删除)。
- 零第三方运行时依赖:只用 node:fs / node:path / node:zlib / node:os。

一、能力

| 功能 | 说明 |
|---|---|
| 列表 | 扫描归档根下所有批次目录,列出每个会话的标题 / 工作目录 / 轮数 / 大小 / 时间(优先读 session_projcache.json,缺失时解会话日志头部兜底) |
| 预览 | 解码会话日志(多帧 zstd 拼接,逐帧解),返回尾部 N 条消息 + 事件类型计数 |
| 恢复 | 两段式:复制 → 逐文件字节校验 → 才删除归档源;目标已存在同名会话时拒绝(绝不覆盖) |
| 删除 | 物理删除归档会话目录(客户端有二次确认弹窗),同时清理批次清单条目 |
| 自动归档 | 可选定时任务:把「超过 N 小时未活跃 + 回合已闭合 + 非空壳」的会话自动搬进归档根。默认关闭,且默认只试跑不搬 |

二、前置条件

- DSH 主包 >= 0.1.1-rc.2 = 20
- 一个能写 profiles// 的 DSH 安装(默认 profile 名为 web)

三、安装(从零开始)

0. 先备份

改 profile 之前先把 profiles//package.json、.package-map.json、cordis.patch.yml
三个文件复制一份留底(改错了好回滚)。

1. 把包放进去

从 git 克隆:

git clone  dsh-archive-sessions

然后在你的 DSH profile 目录里安装它(二选一):

方式 A(推荐,声明式)——在 profiles//package.json 里加一条依赖并安装:

{
"dependencies": {
"dsh-archive-sessions": "file:../../path/to/dsh-archive-sessions"
}
}

cd /profiles/
用你平时给这个 profile 装插件的那条命令安装(pnpm/npm 均可)

方式 B(手动,不装依赖)——直接把包目录复制成实体目录:

cp -r dsh-archive-sessions /profiles//node_modules/dsh-archive-sessions

同时给它补一条 package-map 映射(profiles//node_modules/.package-map.json):

{
"packages": {
"dsh-archive-sessions": { "url": "./dsh-archive-sessions", "dependencies": {} }
}
}

两种方式的差别只在于「谁负责把文件放到 node_modules 下」,插件本身的行为完全一致。

2. 注册插件(关键,别跳过)

必须用 profile 的 cordis.patch.yml 里的 insert 注册,把
cordis.patch.yml.example 里的那段追加进去:

- insert:
- id: dsh-archive-sessions
name: 'dsh-archive-sessions'

⚠️ 不要把它写进 package.json 的 dsh.profile.bundles。本插件的 client 半声明了
dsh.client 而没有 dsh.bundle,放进 bundles 会让 DSH 启动即崩,报
declares no dsh.bundle。client 插件一律走 patch insert。

⚠️ insert 的 id 不能和已有条目重复,重复会崩 duplicate loader entry id。加之前先查:

grep -n "id:" /profiles//cordis.patch.yml

3. 重启 DSH 并验证

重启 DSH → 打开 Web GUI → 硬刷新(Ctrl+Shift+R)→ 进入 设置,左侧应出现
「归档会话管理」分栏。

分栏没出现时按顺序排查:

1. 主进程日志里搜 dsh-archive-sessions(启动失败会留痕);
2. 直接打接口确认 host 半活着:curl http://localhost:3080/api/dsh-archive-sessions/list
(若你改了 server.apiPrefix,用改后的前缀);
3. 确认 .package-map.json 与 node_modules/ 都在位;
4. 确认 cordis.patch.yml 里的 insert 真的被解析到了(重复 id / YAML 缩进错误都会让整段失效)。

四、配置

配置解析优先级(后者覆盖前者):

1. 插件内置默认值(见 examples/archive-sessions.config.example.json)
2. 配置文件
3. 环境变量

配置文件的位置(先找到谁就用谁):

| 优先级 | 路径 |
|---|---|
| 1 | $ARCHIVE_SESSIONS_CONFIG 指向的文件 |
| 2 | /.archive-sessions.config.json ← 一台机器一份,多机共存推荐 |
| 3 | /archive-sessions.config.json |

其中  = $DSH_HOME,未设置时是 ~/.dsh。

支持的环境变量:

| 变量 | 作用 |
|---|---|
| DSH_HOME | DSH 用户数据根(默认 ~/.dsh) |
| DSH_SESSIONS_DIR | 活跃会话目录(默认 /sessions) |
| ARCHIVE_SESSIONS_CONFIG | 配置文件路径 |
| ARCHIVE_SESSIONS_DIR | 归档根目录(默认 /_archived-sessions) |
| ARCHIVE_SESSIONS_API_PREFIX | HTTP 路由前缀 |

路径键写成相对路径时按  解析(例:"archiveRoot": "archive-2" →
/archive-2),所以一份配置可以在 Windows / macOS / Linux 之间搬运,不必写死用户名。

常用键速查(完整默认值与注释见示例文件):

| 键 | 默认 | 说明 |
|---|---|---|
| language | "zh" | 界面语言,内置 zh / en |
| ui / uiByLanguage | {} | 逐条覆盖界面文案;键表见 lib/config.js 的 DEFAULT_UI |
| paths.archiveRoot | null | 归档根;null = /_archived-sessions |
| paths.sessionsRoot | null | 活跃会话根;null = /sessions |
| paths.storagesDir | null | 存储目录;null = /storages |
| archive.headerFrames | 8 | 元数据兜底时向前解几帧(见「已知限制」) |
| archive.statePath | null | 自动归档状态文件路径;null = 归档根下 .auto-archive.json |
| preview.maxMessages | 50 | 预览返回的消息条数 |
| preview.maxMessageChars | 4000 | 单条消息截断长度 |
| server.apiPrefix | "/api/dsh-archive-sessions" | 路由前缀 |
| server.allowedHosts | ["127.0.0.1","localhost","[::1]"] | 允许的 Host 名 |
| auto.enabled | false | 是否开启自动归档 |
| auto.dryRun | true | true 只列候选、不移动文件 |
| auto.hours | 48 | 多少小时未活跃才成为候选 |
| auto.minSizeMb / auto.maxPerRun | 0 / 50 | 候选大小下限 / 单次上限 |

改配置文件后需要重启 DSH 才生效(插件启动时载入一次并常驻内存)。
例外是自动归档的 enabled / dryRun / hours / intervalMs / minSizeMb / maxPerRun——
这几项由面板或 POST {prefix}/auto 维护在状态文件里,改完立即生效。

五、兼容性

支持的主包版本

| DSH 主包 | 状态 | 说明 |
|---|---|---|
| 0.1.1-rc.2 | ✅ 已在真实 DSH 实例上跑通(host 8 路由 + client 分栏全流程,26 项检查) | 当前验证基线 |
| 0.1.1 线其它补丁版 | ✅ 预期可用 | 未逐一实测 |
| >= 0.1.2 且 = 0.2.0 | ❌ 未支持 | 主包尚未发布;破坏性变更宁可显式拒绝 |
| =0.1.1-rc.2  ctx.slots.register(sectionOptions(t), Section));
return;
}
// ② 兜底才试 ctx.settings.installSection,且要求「形参个数  为什么要卡形参个数:installSection 这个名字在新旧语义之间撞名了——
它在 0.1.2+ 里是「把一段配置 schema 注册进 settings 服务」,而本插件要的是
「往设置页插一个 UI 分栏」。不卡参数个数就会把配置注册 API 当 UI API 调用。

host 半注册路由时同样探测:

const server = ctx.webServer ?? ctx.server;   // 不同主包版本暴露的服务名不同
server.register(route);

两处都找不到时会抛一条明确的错误(而不是静默失效)。

本插件刻意不依赖的东西

- 不 import 任何 @deepseek-ai/ 运行时符号(只在 package.json 的 dsh.client.inject
里声明 client 侧依赖名,那是宿主解析用的声明,不是代码 import);
- 不碰 workspaceRegistry / storageDomain / agentPresets / agents 等内部服务
(host 半只 inject ['webServer']);
- 读 session_projcache.json / workspace.json 时按「字段缺了就降级」处理,不假定 schema 版本。

会话日志格式耦合点(升级主包时重点回归)

预览与元数据兜底依赖以下主包事实,主包改格式时这里要跟着改:

- 会话日志 = session.jsonl.zstd(多帧 zstd 拼接,逐帧解;单帧 .jsonl 也支持);
- 事件行 {"type": "session" | "user/message" | "assistant/message" | ...},
文本在 data.content[] / data.message.content[] 里;
- 会话目录名 = 会话 id(session- 或 ,非安全字符会被编码成 ~XXXX);
- sessions/// 的 cwd-key 由工作目录推导(形如 --D-work-proj--)。

六、权限边界与安全设计

| 设计 | 说明 |
|---|---|
| loopback-only | 只接受来自 127.0.0.1 / ::1 的连接,否则 403 |
| Host 白名单 | Host 头必须是配置的 server.allowedHosts 之一 |
| 同源校验 | 有 Origin 时必须与 Host 同源;sec-fetch-site: cross-site 直接拒 |
| 无凭据 | 不存任何密钥 / token;不向外发任何请求 |
| 不越界读写 | sessionId 只允许出现在归档根的子目录名位置:含 / \ . .. 一律 400 |
| 恢复不覆盖 | 目标目录已存在同名会话时返回 409 并放弃,绝不动已有数据 |
| 恢复可回滚 | 复制后逐文件字节校验,不一致就删除副本并保留归档源(返回 500 + 原因) |
| 删除激进但可预期 | 物理删除、不进回收站;UI 有二次确认,API 侧无软删除 |
| 自动归档默认安全 | 默认关闭;开启后默认仍只试跑(dryRun: true),要显式再点一次才真搬 |
| 自动归档判据保守 | 未闭合回合 / 空壳会话一律跳过,候选按最老优先、单次上限可配 |
| 公开配置不含隐私 | GET {prefix}/config 只返回界面文案与阈值,不含任何绝对路径 |

它不做的事(明确声明):不校验调用者身份(假定 DSH Web 只监听 loopback)、
不做速率限制、不加密归档内容(归档目录按你原来的权限暴露)。

七、已知限制

1. 恢复后要重启一次 DSH 才能看到会话回到侧边栏。插件已经把 workspace.json 里的
archivedSessionIds 标记摘掉,但主进程运行中的内存 registry 不同步。
2. 删除不可撤销:不进回收站、没有 undo。请先用「预览」确认内容。
3. 归档目录的批次约定:归档根下按批次目录组织(//),
这是主流的归档脚本约定;若你的会话直接平铺在归档根下,插件会把它当批次名处理、
可能列不出来。可用 archive.manifestFile 配合批次清单([{from,to,mb,ageD}])改善恢复定位。
4. 恢复目标目录推导依赖 cwd → sessions 项目 key 的规则;三者都取不到 cwd 时
落到 archive.unknownCwdKey(默认 _no-cwd),会话能恢复但可能显示在「未知工作目录」分组下。
5. 会话日志格式是主包私有格式,可能随主包升级变化(见第五节末)。
6. 元数据兜底要解头部若干帧(archive.headerFrames,默认 8):只有会话头的帧很小,
所以成本可忽略;但若某会话前 8 帧里都没有 user/message,列表里标题会显示为会话 id 兜底值。
7. 自动归档只处理「目录里放着数据文件的会话」:不负责判断会话是否重要,只按
「未活跃时长 + 回合闭合 + 非空壳」三条机械判据筛选,请先长期用试跑模式观察候选名单。
8. 未做 i18n 全语种覆盖:内置 zh / en,其余语言回退 en。

八、仓库结构

dsh-archive-sessions/
├─ lib/
│  ├─ index.js                 host 半:路由 + 扫描/预览/恢复/删除/自动归档
│  ├─ client.js                client 半:设置页分栏 UI
│  └─ config.js                配置层(默认值 / 文件 / 环境变量 / 校验 / 文案)
├─ examples/
│  └─ archive-sessions.config.example.json   配置示例(含全部默认值)
├─ cordis.patch.yml.example    注册用的 patch insert 片段
├─ scripts/
│  ├─ test-e2e.mjs             端到端测试(干净临时路径 + 独立配置 + 真实 HTTP,跑通全流程)
│  ├─ test-host.mjs            测试宿主:把 host 半挂在最小 webServer 上
│  ├─ verify-source.mjs        静态验证(语法 / 配置行为 / 硬编码与隐私扫描)
│  ├─ verify-publish.mjs       发布后复核(两端 refs 对齐 + 内容级 API 直读 + 匿名可见 + 敏感复扫)
│  ├─ push-publish.mjs         幂等推送器(自检 → 建仓 → 临时带 token URL 推送 → 回读校验)
│  └─ deploy.mjs               幂等部署(认 DSH_HOME,自动备份 + 生成一键回滚)
└─ docs/
└─ RELEASING.md             发布流程(版本号策略 / 变更记录 / 发布前检查单)

九、开发与测试

1) 静态验证:语法 + 配置解析行为 + 硬编码/隐私扫描
node scripts/verify-source.mjs .

2) 端到端:临时目录里造一套假 DSH home(sessions / storages / 归档目录 + 多帧 zstd 日志),
用一份独立配置起真实 HTTP,跑 list / detail / restore / delete / auto / 安全边界
node scripts/test-e2e.mjs          # --keep 保留临时目录便于排查

3) 在真实 DSH 上验证(装到测试实例,别拿正在干活的生产实例试)
启动 DSH 后先 curl 一下 list 路由,再硬刷新 GUI 看分栏

4) 发布后复核(只读;要两端都验就都跑)
node scripts/verify-publish.mjs --owner  --repo dsh-archive-sessions
node scripts/verify-publish.mjs --owner  --repo dsh-archive-sessions --skip-github

5) 发布(幂等;token 走环境变量,不落盘、不写 git remote)
$env:OSS_PUSH_TOKEN=''; node scripts/push-publish.mjs --platform gitee --owner  --repo dsh-archive-sessions

所有脚本都是零依赖的,不需要 npm install。

发布相关的坑(Gitee 建仓默认私有、PATCH 必须带 name、重打 tag 才用 --force 等)记在
docs/RELEASING.md 与本机 oss-publish 技能里。

十、设计依据

本组件是「ops-handoff-design」所述运维体系的一个实现,
设计依据(对应文档仓约定的固定四问):

- 它为什么存在、边界在哪 → 见《自治式运维管家》§2 L4 归档、§6 P2 事件源「归档出错」
- 它与宿主版本的兼容区间 → 见《多机交接与云中继》§4.5「兼容性要求」(另见本 README 第五节)
- 本组件特有的坑与实测 → 见本 README「已知限制」一节,以及 docs/RELEASING.md 的兼容性回归清单
- 文档仓地址 → Gitee(镜像)
| GitHub(主)
(文档仓的组件索引表回指本仓;两仓互链、版本各自独立)

设计稿里不写具体仓库地址(写死即死链),实现清单统一收在文档仓的组件索引表里——本仓只负责回链章节。

十一、许可与致谢

AGPL-3.0(GNU Affero General Public License v3.0),见 LICENSE。

本项目管理在 AGPL-3.0 下开放:个人、学习、开源项目可自由使用与修改。
若需在闭源或商业场景中使用(AGPL 的传染条款不适用),请联系获取商业授权——
本仓暂无公开的联系邮箱,请通过本仓 Issue 联系。
许可变更记录:v0.2.0 及之前为 MIT,v0.3.0 起为 AGPL-3.0。
已经按 MIT 发布的版本,他人已获得的授权收不回——许可变更只约束未来版本(详见 docs/RELEASING.md §许可变更检查)。

会话解码部分参考了 DSH 会话插件生态里公开的 zstd 多帧解码实现思路;
本仓库代码为独立实现,不含任何第三方私有代码或数据。

本仓为开源支线「代码侧」;「方法论文档侧」另有一仓(见上节链接),两仓互链、许可各自独立
(文档侧 CC BY-NC-SA 4.0,代码侧 AGPL-3.0 + 商业授权)。

英文(简版)

dsh-archive-sessions 是 DeepSeek Harness 的一个 Web 插件,
它在设置页面中添加了一个「已归档会话」区块。它管理那些被
物理移出 sessions 目录的会话(移入 /_archived-sessions///),
让你可以列出、预览、恢复和删除它们——外加一个可选的、默认关闭、先试运行的
自动归档器。

- 零运行时依赖(仅 node:fs / node:path / node:zlib / node:os)。
- host 半部分:8 条仅限回环地址的 HTTP 路由。client 半部分:一个设置区块。
- 通过 cordis.patch.yml 的 insert 注册它——绝不要通过 dsh.profile.bundles,
否则 DSH 会因 declares no dsh.bundle 而启动失败。
- 配置文件:$ARCHIVE_SESSIONS_CONFIG,否则 /.archive-sessions.config.json,
否则 /archive-sessions.config.json。相对路径值相对于  解析。
- 支持的 DSH:>=0.1.1-rc.2 <0.2.0(已在 0.1.1-rc.2 上验证;设置区块的注册
会在运行时同时探测新的 ctx.settings.installSection 和旧版 ctx.slots.inject API)。
- 恢复是两阶段的(复制 → 逐字节校验 → 删除源),且绝不覆盖已存在的会话。
- 删除是永久性的。自动归档默认禁用,且默认为试运行。

以 AGPL-3.0 许可(见 LICENSE)。可自由用于个人、
教育和开源项目的使用与修改。对于 闭源或商业 用途(AGPL 的
copyleft 不适用),可提供 商业许可——在本仓库中开一个 issue
即可联系。许可历史:至 v0.2.0(含)为 MIT,自
v0.3.0 起为 AGPL-3.0*(许可变更仅约束未来版本)。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

同作者(kira905)的其他插件

💬 加入社群

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

DPharness QQ 群二维码,QQ 扫码进群
QQ 扫码进群
DPharness 飞书群二维码,飞书扫码进群
飞书扫码进群