Bundle
dsh-archive-keeper
归档守护:DSH 会话归档后**自动**提炼要点,并在对话头部加一个「归档守护」视图,由你自己决定每条归档的去留(保留原文 / 只留摘要 / 彻底删除,删除可恢复)。提炼失败会自动重试,重试用尽后可在「提炼失败」里一键删除。仅桌面版 / 网页版生效。
- Source
- Isle-ux
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 2 days ago
Readme
# dsh-archive-keeper(归档守护) > [English](README.en.md) | 中文 DSH 的「归档」只改标记、不动磁盘。时间一长,`$DSH_HOME/sessions/` 会堆下一大坨再也不会翻的原文。 这个插件把归档会话**自动提炼成结构化要点**,并在对话头部加一个「归档守护」面板,让你逐条决定去留 —— 而且**任何删除都先移入回收站,随时可恢复**。 > 本包随附全部运行所需代码,安装后即可独立运行。 --- ## 功能 ### 1. 归档后自动提炼 轮询归档列表,一出现新的归档会话就调起提炼流程,把整个会话压成结构化要点: 概括 / 决定 / 事实 / 交付物 / 待办项 / 可作废项,并给出「是否值得留存」的判断。 ### 2. 由你自己定去留 对话头部右侧的「归档守护」面板里,每条归档都是一个可展开的卡片: | 选项 | 含义 | | --- | --- | | **保留原文** | 什么都不删 | | **只留摘要** | 删除原文,只保留提炼出的要点 | | **彻底删除** | 原文和摘要都移入回收站 | | **恢复原文** | 把之前移入回收站的原文搬回来 | ### 3. 时间段 + 标签 分组 面板里的对话按 **年份 → 日期 → 时段 → 标签** 四级归类: - 年份、日期:越新的越靠上(从远到近、从下到上) - 时段:**上午 / 下午 / 晚上**(< 12:00 / 12:00–17:59 / ≥ 18:00) - 标签:自己在齿轮面板里定义,没打标签的归入「未分类」 ### 4. 自定义「值得留存」的价值判断 点右上角 **⚙** 打开个性化面板: - **标签**:内置一批常见标签(重要 / 环境事实 / 用户偏好 / 教训 / 待跟进 / 可复用 / 项目 / 灵感),也可自己新建;给任意对话手工打标签。 - **收纳规则**:按**关键词 / 分类 / 用户轮数区间**组合条件(多条件是「且」)。**命中规则的会话优先纳入「值得留存」**;没命中任何规则的,才回落到默认价值判断。 - **自动打标签**:只自动贴标签,不改变收纳结果。 ### 5. 回收站 所有被删除的内容(原文与摘要)都先移入 `trash/`,面板顶部显示回收站占用,可逐条恢复或清空。 ### 6. 实时计数 对话头部的「归档守护」按钮旁显示四个数字: ``` 归档总数 15 · 已提炼 15 · 无法提炼 0 · 待提炼 0 ``` 四者恒自洽(`归档总数 = 已提炼 + 无法提炼 + 待提炼`),并且**跟着当前还剩哪些归档会话实时变化**: - 取消归档一个会话 → 归档总数立刻下降 - 摘要被删掉 → 已提炼立刻下降、待提炼相应上升 - 会话原文已从磁盘删除 → 计入「无法提炼」,不再反复重试 - 正在提炼时,数字后面会追加 `· 提炼中…` ### 7. 提炼失败 提炼**全自动**:归档一个会话后,插件自己发现并开始提炼,**不需要你点任何按钮**。 偶发失败(网络超时、额度用尽之类)也会**自动重试,最多 3 次**。只有重试全部用尽, 该会话才会出现在筛选栏的 **「提炼失败 N」** 里(红色,平时不占位,没有失败项时整组不显示)。 点开这条会话,会看到失败原因和失败时间,以及唯一的处置按钮 **「删除」**。这类会话没有摘要 可恢复,所以删除只是把它从归档列表里移除(兜底恢复靠 DSH 自己的 `workspace.json` 备份)。 > **为什么没有「重新提炼」按钮?** v1.1.0 曾有,但它会导致界面卡住:按钮背后的接口要做全量 > 磁盘 IO,前端又在轮询它,两者叠加就把对话界面堵死。v1.3.0 把按钮和它背后的 `/run`、`/retry` > 路由一起删掉了 —— **去掉触发入口,而不是修触发入口**,这样这类卡死从结构上不可能再发生。 --- ## 更新日志 ### v1.3.0 **核心变化:提炼彻底改为全自动,并删掉「重新提炼」按钮。** 1. **提炼不再需要任何手动操作。** 此前只有归档列表**变长**时才会触发提炼,而且「重新提炼」按钮是唯一的补跑手段。 现在改为:只要归档列表有任何变化就检查一遍,且每次启动都做一次兜底补扫, 凡是没处理完的都自动处理。**你归档完就不需要再管了。** 2. **删掉「重新提炼」按钮,连同它背后的 `/run` 与 `/retry` 路由。** v1.1.0 声称修好了「点重新提炼卡住界面」,但那个修复是治标的——它只是把按钮在提炼期间 置灰,而卡死的真正原因是**接口本身**:它做全量磁盘 IO,前端又在轮询它。 这次直接把触发入口整个拿掉,从结构上消除这类卡死(详见上文「提炼失败」一节)。 3. **失败改为自动重试,重试用尽后才记「提炼失败」。** 新增 `attempts` 计数(最多 3 次,可用 `ARCHIVE_KEEPER_MAX_ATTEMPTS` 调整)。 在此之前失败一次就永久记成 `error` 且不再自动重试。现在: - 还在重试中的失败**计入「待提炼」**,不会过早打扰你 - 3 次用尽才进入「提炼失败」独立分组(红色,没有失败项时整组不显示) - 该分组里提供唯一的处置:**「删除」**(这类会话没有摘要可恢复) 4. **修掉「只留摘要的会话永远显示未提炼」。** 判据从「state 里记着 ok」改为「**state 记着 ok,或摘要文件确实存在**」。 此前「只留摘要」会连摘要一起清掉,于是这些会话 state 是 `ok`、却既没有摘要也不被计入已提炼, 数字永远对不上(实测表现为「归档 15 / 已提炼 11」,4 条怎么都消不掉)。修复后为 15/15。 5. **原文已丢失的会话改为自动清理。** 以前 `missing` 会永久占着「无法提炼」的计数。现在确认原文确实不在磁盘上之后, 自动把它从归档列表移除(可用 `--no-purge` 关闭)。**`error` 不清理** —— 两种状态是两回事:一个是原文没了、没得救,一个是还能重试。 6. **重写提炼提示词,要点质量明显提升。** 明确了「自足、具体、有用、不编造、不写套话」的写作要求,并列出重点抓取的几类信息 (用户偏好与禁忌 / 纠正与不满 / 环境事实 / 技术决策及理由 / 产出文件绝对路径 / 踩坑与解法 / 未完成事项),配了「差例 / 好例」对照。实测同一条真实会话,要点从「排查了报错、进行了修复」 这类套话,变成 8 条各自可独立读懂、带具体路径和版本号的结论。 7. **「提炼失败」的删除动作带双重安全闸。** 宿主侧要求会话确实处于 `error` 状态、且重试已用尽才允许删除;keeper 侧再次校验状态。 两层都过不了就拒绝,避免任何形式的「任意删除」后门。 ### v1.2.0 **修复三个问题、修好一处隐藏崩溃:** 1. **提炼过的会话不该再被反复重试。** 有些会话**永远无法提炼**——原文已被你从磁盘上删掉(`missing`),或者提炼确实失败了(`error`)。 此前判据是「只要不是 ok 就算待处理」,于是这些死记录**每次运行都会被重新挑中**, 「待提炼」数永远降不到 0,看起来就像卡住了。现在把它们标为**终态**并跳过: - 数量单独显示为「无法提炼 N」,不再混进「待提炼」 - 每次运行都会写明跳过了几个、分别是什么原因 - 想重试时用 `--retry-failed` 显式要求(命令行),平时不再自动重试 2. **提炼日志落盘。** 新增 `state/keeper.log`,记录每次启动、每个会话的处理结果、跳过原因,以及异常退出时的尾部输出。 出问题时不用再靠复现,直接看日志。日志超 1 MB 自动留最后 2000 行轮转,不会无限增长。 3. **模型输出被截断时不再白跑一趟。** 模型回复偶尔会被长度上限截断,末尾少个 `}` 或半条数组,`JSON.parse` 直接失败, 整个会话就被记成 `error`。现在会尝试**把不完整的 JSON 补全后重新解析**: 能救回多少字段就留多少(例如保住 summary 与已列出的要点),确实救不回来的才判失败。 > 「救不回来」是有意为之:如果截断点落在某个值的字符串中间,硬拼出来会得到一个被腰斩的 > 摘要(如 "排查本机资源…确认无异"),比没有更误导人,这种情况一律放弃。 4. **修掉 `extract.cjs` 里一处隐藏的 `ReferenceError`。** 会话元数据缺失时会抛 `file is not defined`(`file` 是另一个函数的形参,不在该作用域内), 导致该会话必然失败。真实会话把 id 放在事件顶层,所以这条路径平时走不到—— 属于「一旦触发就必然失败、且极难排查」的那类问题,已一并修掉。 ### v1.1.0 **修复两个问题:** 1. **提炼完成后再次点击「重新提炼」会卡住界面。** 此前宿主的路由无论提炼是否真的启动,都回报“已启动”,前端也就一直显示等待状态; 而按钮在提炼进行中既没有置灰、也没有拦截重复点击。当时做了如下缓解: - 提炼进行中,按钮变为「提炼中…」并置灰,点它不会有任何反应 - 宿主如实回报是否真的启动了提炼,前端据此给出正确提示 - 提炼进行中自动提高刷新频率,跑完立即恢复可点 > ⚠️ **这次修复是不完整的**,问题在 v1.3.0 之前复发(本质是接口在阻塞式地做全量磁盘 IO, > 前端还在轮询它)。v1.3.0 已把按钮与相关路由整体删除,请以 v1.3.0 的行为为准。 2. **「归档总数 / 已提炼」只记历史累计,不会随实际变化。** 此前这两个数字取自“历史上处理过的会话总数”,只增不减,会和列表对不上。现在改为**实时统计**, 以当前归档列表为准,取消归档 / 删除摘要后数字立刻同步。 ### v1.0.0 首个正式版本。 --- ## 安装 有三种方式,任选其一。 ### 方式一:从 GitHub 直接安装(推荐) ```bash npm i git+https://github.com/Isle-ux/dsh-archive-keeper-plugin.git ``` > ⚠️ **不要**写成 `npm i github:Isle-ux/dsh-archive-keeper-plugin`。 > npm 会把 `github:` 简写改写成 **SSH**(`ssh://git@github.com/...`), > 没有配 SSH key 的机器会直接报 `Permission denied (publickey)`。 > 用上面这种显式的 `git+https://` 形式走 HTTPS,任何人都能装。 如果网络访问 GitHub 不稳,可改用镜像源: ```bash npm i git+https://github.com/Isle-ux/dsh-archive-keeper-plugin.git --registry=https://registry.npmmirror.com ``` ### 方式二:下载 Release 里的压缩包 到 [Releases](https://github.com/Isle-ux/dsh-archive-keeper-plugin/releases) 页面下载 `dsh-archive-keeper-<版本>.tgz`,然后本地安装: ```bash npm i ./dsh-archive-keeper-1.2.0.tgz ``` 这种方式不依赖 GitHub 连通性,网络不好时最稳。 同一个 Release 里附有 `.sha256` 校验和,可用来核对下载是否完整: ```bash sha256sum -c dsh-archive-keeper-1.2.0.tgz.sha256 # Linux / macOS certutil -hashfile dsh-archive-keeper-1.2.0.tgz SHA256 # Windows ``` ### 方式三:克隆源码 ```bash git clone https://github.com/Isle-ux/dsh-archive-keeper-plugin.git ``` --- 装好后,把插件加进 profile 的 `dsh.profile.bundles`(或按你的 DSH 版本的插件安装方式装载)。 本包**自带全部运行代码**,不需要额外安装运行时依赖。 ### 兼容性 - **开发与验证环境:DSH `0.2.0-rc.2`**(桌面版 / Windows 11)。本插件在该版本上完整验证通过。 - 仅**桌面版 / 网页版**生效:界面半边注册在 `conversation.session.header.utilities` 座位,只有带对话区的宿主才声明这条座位;headless、tui 等宿主里插件不会激活。 - 需要 Node.js ≥ 20。 - 提炼步骤会调用模型,需要在 DSH 里配好可用的模型路由。 > ⚠️ 本插件是按 DSH `0.2.0-rc.2` 开发的。如果你的 DSH 版本对插件清单有不同要求 > (比如 `dsh.client` 字段格式),可能需要按你的版本调整 `package.json`。 ### 与其他插件的兼容性 **结论先说:本插件不会与其他插件冲突。** 原因在于 DSH 的座位机制本身允许多插件共存 —— 下面说清楚边界,以及唯一一种可能出问题的情况。 **① 座位是「列表」,天生支持并列** `conversation.session.header.utilities` 是 `kind: "list"` 的座位,意思是它可以挂**多个**注册项,按 `priority` → `order` 排序依次渲染。不是"一个位置只能塞一个插件"的那种独占座位。 **唯一会冲突的条件**是:另一个插件往**同一条座位**注册了**完全相同的 `id` 且 `priority` 也相同**。此时 DSH 会直接抛错: ``` list slot "..." already has an entry with id "..." (registered by ...) ``` 本插件使用的 id 带自己的命名空间,与常见插件的 id 不会撞车。所以正常情况下不会出现这种情况。 **② 你不需要为本插件取舍别的插件** 如果你的 DSH 里同时装了其他往对话头部塞按钮的插件(例如各种用量统计、模型切换类插件),它们会和「归档守护」**并排显示**,而不是互相顶掉。作者本机同时装着 12 个插件(含多个带客户端界面的),本插件的座位上没有出现任何注册冲突。 **③ 一个已知的、与我无关的座位冲突(供参考)** 作者本机实测发现 `@ychris12138/dsh-usage-stats` 与 `@changfenhuang/dsh-genui` 两个插件都往 `panel.badge` 注册,这属于那两个插件之间的事,与归档守护无关,这里仅作为"座位冲突长什么样"的例子提及。 **④ 我无法保证的部分(诚实说明)** - **不同 DSH 版本的座位名可能不同。** `conversation.session.header.utilities` 是 DSH `0.2.0-rc.2` 的座位名。如果你的 DSH 版本没有这条座位,插件界面半边**不会报错,但也不会显示** —— 宿主半边(提炼、路由、回收站)仍然正常工作。 - **我没有在所有 DSH 版本上测试过。** 本插件只在 DSH `0.2.0-rc.2`(Windows 11 桌面版)验证过 —— 完整 12 插件栈、真实浏览器、0 报错。如果你装了之后发现问题,欢迎提 Issue 并附上你的 DSH 版本号。 - **没有声明版本约束。** 我没找到 DSH 官方的插件规范文档,所以 `package.json` 里没有写 `dsh` 的版本范围。如果你的版本装载失败,多半是清单字段格式差异,按你的版本调整即可。 --- ## 配置 | 键 | 默认 | 说明 | | --- | --- | --- | | `root` | `<用户目录>\Documents\deepseek-harness\archive-keeper` | 用户数据根目录(摘要、选择、回收站都写在这里) | | `pollMs` | `30000` | 归档列表轮询间隔(毫秒) | > `root` 指向的是**你的数据目录**,与插件安装位置无关;升级或重装插件不会影响已有数据。 --- ## 路由 | 方法 | 路径 | 作用 | | --- | --- | --- | | GET | `/archive-keeper/list` | 全部摘要 + 你的选择 + 原文是否还在 | | POST | `/archive-keeper/decide` | 记录保留原文 / 只留摘要 / 恢复原文 | | POST | `/archive-keeper/run` | 立即跑一次增量提炼 | | GET | `/archive-keeper/customize` | 读取标签与规则 | | POST | `/archive-keeper/tag` | 增删标签、手工打标签 | | POST | `/archive-keeper/rule` | 增删改收纳规则 / 自动打标签规则 | --- ## 安全边界(重要) - **本插件永不自动删任何东西。** 删除只发生在你显式点击并二次确认之后。 - 删除是**移动**到 `trash/<会话id>__<时间戳>/`,不是真删;随时可以搬回去。 - 每次清理都记一笔到 `state/purge-log.json`(原路径、去向、字节数)。 - **清空回收站是唯一不可逆的操作**,会二次确认后连摘要一起删除。 --- ## 目录结构 ### 插件包 ``` dsh-archive-keeper/ lib/index.js 宿主半边:归档监听 + HTTP 路由 lib/client.js 浏览器半边:「归档守护」面板 lib/state.cjs 状态机 / 排他锁 / 摘要读写 lib/keeper.cjs 主流程:扫描 → 抽取 → 模型提炼 → 落盘 lib/extract.cjs 会话文件解析(zstd 多帧解压 + 脉络抽取) lib/decisions.cjs 去留选择、回收站、彻底删除 lib/tags.cjs 标签与自定义价值规则 cordis.patch.yml bundle patch(只 insert 自己这一行) ``` ### 用户数据目录(`root` 指向处) ``` archive-keeper/ digests/<会话id>.json 每个归档会话的结构化要点 state/state.json 已处理记录 state/decisions.json 你的选择 state/tags.json 标签与规则(首次自定义后才创建) state/latest.json 最近一次运行的报告 state/purge-log.json 清理日志 trash/<会话id>__<时间戳>/ 被清理的原文(可恢复) ``` --- ## 命令行(不走界面时) ```bash node lib/keeper.cjs # 增量提炼新归档 node lib/keeper.cjs --all # 重跑全部 node lib/keeper.cjs --no-llm # 只抽取不调模型(离线自检) node lib/decisions.cjs list # 看当前选择 ``` --- ## 提炼用的模型 默认走 `headless` profile。想换成别的路由,设环境变量 `ARCHIVE_KEEPER_PROFILE=<profile名>` 即可。 --- ## License MIT
Install
dsh plugin --profile web add github:Isle-ux/dsh-archive-keeper-plugin
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-archive-keeper from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.